[squeak-dev] Will Newspeak be callable by external programs?

John M McIntosh johnmci at smalltalkconsulting.com
Sun Feb 8 21:59:12 UTC 2009


Ok, let me ramble.

Well in the far past for the macintosh we built a plugin for the  
browser.

The plugin used the netscape browser api to interface to the netscape  
and IE browser.
When the plugin was loaded it would set things up, and start running  
the bytecode interpreter.

The VM can be viewed as endless loop, however it is possible to exit  
the loop and return to the caller
and of course save the interpreter stack state.  Later the caller  
reenters the interpreter loop and continues
execution.

This logic still exists see

http://isqueak.org/browserPluginReturnIfNeeded

In the early part of the decade I change the logic a bit so that the  
interpreter was spin off as a separate pthread within
the browser to give us better performance and visual updating.


The Hydra VM still exploits this idea of returning from the  
interpreter loop where it does

	lockInterpreter(intr); /* lock interpreter mutex before entering loop  
*/
	while (1)
	{
		interpret(intr);
		// give a chance other threads to do something
		unlockInterpreter(intr);
		lockInterpreter(intr);
		pokeAtTimer(intr);
		handleEvents(intr);
	}


In this case the interpret() is the endless bytecode interpreter loop,  
which is exited, then the handleEvents
pulls inter-interpeter events off the queue and we re-enter the  
interpreter.  The other point is the program setups each
VM on a seperate pthread.


The iPhone VM actually runs the VM in a background thread

	 // Run the squeak process in a worker thread
	
	[NSThread detachNewThreadSelector: @selector(runSqueak)
							 toTarget:	self.squeakApplication
						   withObject:	NULL];


For the current Unix and macintosh browser plugin we take a different  
approach where the plugin launches a separate
Squeak VM process and uses pipes and shared memory to move items of  
interest between the two process.  So UI gestures enter the browser  
plugin
and are sent by a pipe to the squeak process, the squeak process  
interpreters them, and does updates to it's internal Screen. For the  
unix port that's
a X11 screen hosted by the browser, for the carbon VM it's more  
complicated and has to us a shared memory location and pipe to ask the  
browser
plugin to draw the screen within the address space of the browser.    
Lastly the VM can make requests back to the browser, say to download a  
file, again
by sending a message via the pipe.

Astute macintosh folks might note for years now the Squeak carbon app  
will act as a Service, if you have a Squeak image that contains the  
macintosh services logic
it's possible for you to select smalltalk code in TextEdit, then say  
Services->Squeak DoIt and Squeak will get the services request, do it,  
and return the results.

Now for your problem.


(a) You want to run the VM, you can choose to run the VM either as  
part of a currently executing caller thread, or as a pthread, or as a  
separate process.
(b) You need to choose if you want to start the VM, execute some sort  
of startup script & data, return results, and quit.
(b) or pass a request to execute something, and return the result  
somehow.   There are many ways to do that, file based message passing,  
pipes, queues, shared memory, etc....

The Alien FFI work, or the older FFI logic will help you extract  
information from memory and/or call API routines hosted by the  
operating system or any other loadable DLL.
The Alien FFI work has logic to let you call back to a squeak method  
from a blocking API call that requires you to provide executable entry  
points, an example given
is the sort callback where the executable entry point you provide is a  
smalltalk method to compare floating point numbers.


What I'd suggest is having your plugin start the VM as a separate  
pthread with a thread safe queue, and location for the squeak external  
semaphore number. Your Squeak image would startup and wait on the  
semaphore.  Later when your CAD system invokes the plugin with lots of  
parameter data you build a queue object, put it on the queue, trigger  
the squeak semaphore and wait.... , once the waiting ends you have  
someway to pull the results that Squeak has made for you, likely  
populate the queue item with return data, and or of course the squeak  
vm could have manipulated the data to no end.

I'll note for the Objective-C bridge I'm working on for the iPhone has  
this chunk of code below (original donated by Avi)

What happens here is a message send occurs to a squeak proxy object,  
if the message selector is one we
are interested in we set a pthread conditional lock to :0, then unlock  
to 1, then signal the squeak semaphore.
the waiting squeak process then locks to condition 1, and the  
objective C code below then attempts an unlock to
condition 2 and will block as the squeak process runs using the  
NSInvocation instance which contains information
about the message send, all the parms and has the ability to set the  
return value.  Effectively we have the entire message
implementation in Smalltalk.  Once the Smalltalk logic completes it  
unlocks condition with condition 2 which lets the  ockWhenCondition: 2
thus letting the forwardInvocation: terminate.

In this case the SqueakProxy instance is being sent messages on the  
main thread, and the squeak VM is on another thread
the conditional lock control which thread gets   executed and the  
invocation instance variable is the shared object.

So what about NSDate?   The issue with passing data to complex third  
party is how long do you wait for the third party
to complete the request. What if your Smalltalk logic is flawed, and  
you get a walkback? Do you wait and time out or
do you return a bad value event by trapping the unhandled walkback?

- (void) forwardInvocation: (NSInvocation*) anInvocation
{
	NSDate *timeout;
	if (![sigs containsObject: NSStringFromSelector([anInvocation  
selector])]) {
		return;
	}
	
	if([lock lockWhenCondition: 0 beforeDate: (timeout = [[NSDate alloc]  
initWithTimeIntervalSinceNow: 3])])
	{
		[lock unlockWithCondition: 1];
		[timeout release];
		invocation = [anInvocation retain];
		
		interpreterProxy->signalSemaphoreWithIndex(sem);
		if([lock lockWhenCondition: 2 beforeDate: (timeout = [[NSDate alloc]  
initWithTimeIntervalSinceNow: 4])])
		{
			[timeout release];
			[invocation release];
			[lock unlockWithCondition: 0];
		}
		else
		{
			[timeout release];
			[invocation release];
			[lock unlockWithCondition: 0];
		}
	}
	else
	{
		[timeout release];
		//NSLog(@"failed lock 0");
	}
}


On 8-Feb-09, at 11:28 AM, askoh wrote:

>
> For about a year now, I have been asking if Squeak can be called by  
> external
> programs, if it can be controlled by a non-Squeak program, if it can  
> be used
> to make plugins or addons in CAD programs. And I have not received  
> an answer
> that says that it is possible now nor anyone working on that for the  
> future.
> If Alien FFI can do it I would be most happy to try it immediately.  
> Can the
> author of Alien FFI give an authoritative answer to its capability  
> to do the
> above? Is there documentation to describe how? Thanks in advance.
>
> All the best,
> Aik-Siong Koh

--
= 
= 
= 
========================================================================
John M. McIntosh <johnmci at smalltalkconsulting.com>
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
= 
= 
= 
========================================================================






More information about the Squeak-dev mailing list