Skip to content

Commit

Permalink
Merge pull request #195 from klippa-app/feature/fix-concurrent-map-wr…
Browse files Browse the repository at this point in the history
…ites

Fix concurrent map writes
  • Loading branch information
jerbob92 authored Nov 19, 2024
2 parents bc09fa2 + cb7b22f commit 5590015
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 15 deletions.
42 changes: 29 additions & 13 deletions internal/implementation_webassembly/fpdf_progressive.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package implementation_webassembly

import (
"errors"
"sync"
"unsafe"

"github.com/klippa-app/go-pdfium/enums"
Expand All @@ -18,10 +19,15 @@ type PauseHandle struct {
Callback func() bool
}

var PauseHandles = map[references.FPDF_PAGE]*PauseHandle{}
var PauseHandles = struct {
Refs map[references.FPDF_PAGE]*PauseHandle
Mutex *sync.RWMutex
}{
Refs: map[references.FPDF_PAGE]*PauseHandle{},
Mutex: &sync.RWMutex{},
}

// FPDF_RenderPageBitmap_Start starts to render page contents to a device independent bitmap progressively.
// Not supported on multi-threaded usage.
func (p *PdfiumImplementation) FPDF_RenderPageBitmap_Start(request *requests.FPDF_RenderPageBitmap_Start) (*responses.FPDF_RenderPageBitmap_Start, error) {
p.Lock()
defer p.Unlock()
Expand Down Expand Up @@ -58,7 +64,9 @@ func (p *PdfiumImplementation) FPDF_RenderPageBitmap_Start(request *requests.FPD
Callback: request.NeedToPauseNowCallback,
}

PauseHandles[pageHandle.nativeRef] = pauseHandle
PauseHandles.Mutex.Lock()
PauseHandles.Refs[pageHandle.nativeRef] = pauseHandle
PauseHandles.Mutex.Unlock()

res, err = p.Module.ExportedFunction("FPDF_RenderPageBitmap_Start").Call(p.Context, *bitmapHandle.handle, *pageHandle.handle, *(*uint64)(unsafe.Pointer(&request.StartX)), *(*uint64)(unsafe.Pointer(&request.StartY)), *(*uint64)(unsafe.Pointer(&request.SizeX)), *(*uint64)(unsafe.Pointer(&request.SizeY)), *(*uint64)(unsafe.Pointer(&request.Rotate)), *(*uint64)(unsafe.Pointer(&request.Flags)), pausePointer)
if err != nil {
Expand All @@ -84,11 +92,13 @@ func (p *PdfiumImplementation) FPDF_RenderPage_Continue(request *requests.FPDF_R
}

// Check if we already have the reference. Clean it up.
if _, ok := PauseHandles[pageHandle.nativeRef]; ok {
p.Free(PauseHandles[pageHandle.nativeRef].Pointer)
p.Free(PauseHandles[pageHandle.nativeRef].StringRef)
delete(PauseHandles, pageHandle.nativeRef)
PauseHandles.Mutex.Lock()
if _, ok := PauseHandles.Refs[pageHandle.nativeRef]; ok {
p.Free(PauseHandles.Refs[pageHandle.nativeRef].Pointer)
p.Free(PauseHandles.Refs[pageHandle.nativeRef].StringRef)
delete(PauseHandles.Refs, pageHandle.nativeRef)
}
PauseHandles.Mutex.Unlock()

pausePointer := uint64(0)
if request.NeedToPauseNowCallback != nil {
Expand All @@ -109,7 +119,9 @@ func (p *PdfiumImplementation) FPDF_RenderPage_Continue(request *requests.FPDF_R
Callback: request.NeedToPauseNowCallback,
}

PauseHandles[pageHandle.nativeRef] = pauseHandle
PauseHandles.Mutex.Lock()
PauseHandles.Refs[pageHandle.nativeRef] = pauseHandle
PauseHandles.Mutex.Unlock()
pausePointer = newPausePointer
}

Expand Down Expand Up @@ -142,11 +154,13 @@ func (p *PdfiumImplementation) FPDF_RenderPage_Close(request *requests.FPDF_Rend
}

// Check if we have the reference. Clean it up.
if _, ok := PauseHandles[pageHandle.nativeRef]; ok {
p.Free(PauseHandles[pageHandle.nativeRef].StringRef)
p.Free(PauseHandles[pageHandle.nativeRef].Pointer)
delete(PauseHandles, pageHandle.nativeRef)
PauseHandles.Mutex.Lock()
if _, ok := PauseHandles.Refs[pageHandle.nativeRef]; ok {
p.Free(PauseHandles.Refs[pageHandle.nativeRef].StringRef)
p.Free(PauseHandles.Refs[pageHandle.nativeRef].Pointer)
delete(PauseHandles.Refs, pageHandle.nativeRef)
}
PauseHandles.Mutex.Unlock()

return &responses.FPDF_RenderPage_Close{}, nil
}
Expand Down Expand Up @@ -189,7 +203,9 @@ func (p *PdfiumImplementation) FPDF_RenderPageBitmapWithColorScheme_Start(reques
Callback: request.NeedToPauseNowCallback,
}

PauseHandles[pageHandle.nativeRef] = pauseHandle
PauseHandles.Mutex.Lock()
PauseHandles.Refs[pageHandle.nativeRef] = pauseHandle
PauseHandles.Mutex.Unlock()

colorSchemeSize := p.CSizeULong() * 4
colorScheme := uint64(0)
Expand Down
6 changes: 4 additions & 2 deletions webassembly/imports/callbacks.go
Original file line number Diff line number Diff line change
Expand Up @@ -550,12 +550,14 @@ func (cb IFSDK_PAUSE_NeedToPauseNow_CB) Call(ctx context.Context, mod api.Module
}

// Check if we still have the reference.
if _, ok := implementation_webassembly.PauseHandles[references.FPDF_PAGE(string(stringRef))]; !ok {
implementation_webassembly.PauseHandles.Mutex.RLock()
defer implementation_webassembly.PauseHandles.Mutex.RUnlock()
if _, ok := implementation_webassembly.PauseHandles.Refs[references.FPDF_PAGE(string(stringRef))]; !ok {
stack[0] = api.EncodeI32(int32(1))
return
}

shouldPause := implementation_webassembly.PauseHandles[references.FPDF_PAGE(string(stringRef))].Callback()
shouldPause := implementation_webassembly.PauseHandles.Refs[references.FPDF_PAGE(string(stringRef))].Callback()
if shouldPause {
stack[0] = api.EncodeI32(int32(1))
return
Expand Down

0 comments on commit 5590015

Please sign in to comment.