I've been looking at the iOS external SDK / guide and it seems like a lot of it corresponds to bits of LCB/FFI but with certain things missing from LCB. I think these are things that I may need to get some problematic things working in LCB.
It seems LC runs on two threads, one for the main app/UI, and a seperate thread for script execution. That's a separate RunLoop? Blocks were recently added to the Objective C module, are Blocks executed on the main/system as in 'LCRunBlockOnSystemThread''? Is a Block passed to a foreign function 'owned' by the LC engine / main app thread?
Where does the LCB fall in with this setup? Is LCB / FFI in a separate "context" or thread or RunLoop ? What is the RunLoop mode? Are there things that can't be done with LCB/FFI that CAN be done with an External?
From the iOS External Dev Guide:
Code: Select all
Threading
The engine runs using two threads in a co-operative fashion with only one executing at a time. The first (main/system) thread is where all system related calls are made – for example, manipulating UIViews or any other system-provided classes. The second (engine/script) thread is where code that executes scripts run.
The reason for this separation is the existence of ‘wait’ – the ability to block an executing handler while events are processed. On iOS, in order to process events, the system thread must return to the core event loop which iOS manages; however waiting requires running the event loop from nested calls. To make this work, when the engine thread invokes a wait, the engine jumps to the system thread, jumping back when an event occurs.
As most iOS system classes are UI / RunLoop related, it is critical that they be manipulated on the system thread, rather than the engine thread. To do this there are two choices:
If an external handler does not use any LC API calls that might call script (and thus invoke ‘wait’) then it can be marked as a ‘tail’ call in the idl – for example:
tail function rreMicrophoneIsAvailable
If marked as a ‘tail’ call then the handler will be invoked on the system thread, meaning no extra code is needed.
If an external handler does use LC API calls that might call script (and thus invoke ‘wait’) then ‘tail’ cannot be used. Instead, there are two new LC API calls LCRunOnSystemThread and LCRunBlockOnSystemThread . These allow code to be execute on the system thread, from the engine thread. See the SDK examples for ways this is done.
Code: Select all
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x00007fff3fea80c0
Exception Note: EXC_CORPSE_NOTIFY
VM Regions Near 0x7fff3fea80c0:
MALLOC_TINY 00007fff3e800000-00007fff3fe00000 [ 22.0M] rw-/rwx SM=PRV
--> MALLOC_TINY 00007fff3fe00000-00007fff3ff00000 [ 1024K] rw-/rwx SM=COW
MALLOC_TINY 00007fff3ff00000-00007fff40000000 [ 1024K] rw-/rwx SM=PRV
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 ??? 0x00007fff3fea80c0 0 + 140734265721024
1 com.apple.audio.midi.CoreMIDI 0x0000000110f156f4 _XNotify + 74
2 com.apple.audio.midi.CoreMIDI 0x0000000110f316dd mshMIGPerform + 248
3 com.apple.CoreFoundation 0x00007fff9a10a7e9 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
4 com.apple.CoreFoundation 0x00007fff9a10a761 __CFRunLoopDoSource1 + 465
5 com.apple.CoreFoundation 0x00007fff9a1023d5 __CFRunLoopRun + 2389
6 com.apple.CoreFoundation 0x00007fff9a101824 CFRunLoopRunSpecific + 420
7 com.apple.HIToolbox 0x00007fff99661ebc RunCurrentEventLoopInMode + 240
8 com.apple.HIToolbox 0x00007fff99661bf9 ReceiveNextEventCommon + 184
9 com.apple.HIToolbox 0x00007fff99661b26 _BlockUntilNextEventMatchingListInModeWithFilter + 71
10 com.apple.AppKit 0x00007fff97bf6a04 _DPSNextEvent + 1120
11 com.apple.AppKit 0x00007fff983727ee -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 2796
12 com.runrev.livecode 0x000000010873fcb4 0x108420000 + 3275956
13 com.runrev.livecode 0x0000000108731818 0x108420000 + 3217432
....
The callback I'm trying to use in this specific crash is MIDINotifyProc which has this note on Apple's dev site:
I think "The same thread on which you called the MIDIClientCreate" would be whatever thread the LCB FFI library is running in.Discussion
The MIDINotifyProc callback function is invoked on the same thread on which you called the MIDIClientCreate function