Ruby Cocoa Run Loop

B

Benjohn Barnes

Hello,

I've been inspired by reading:

http://www.rubycocoa.com/mastering-cocoa-with-ruby/1

But I don't really want to have to build an application that's a ruby
console.

I'd like to be able to fire up the NSApplication's run loop from
within a new NSThread. My thinking is that if I do this from IRB, I
can then continue to use the original thread. I'll have a proper
application run loop that's able to respond to events, but I'll also
be able to continue developing code live within irb. Obviously, I'll
have to be very careful in interacting with the main application, but
I think it ought to be possible with:

performSelectorOnMainThread_withObject_waitUntilDone.

:) I suspect I'm being naive in the extreme to even expect this to
work. But as an optimist, I thought I'd see what happened if I tried.
Here's my code:

####
class ApplicationRunner < OSX::NSObject
def run
pool = OSX::NSAutoreleasePool.alloc.init
NSApplication.sharedApplication.run
pool.release
end
end

runner = ApplicationRunner.alloc.init
OSX::NSThread.detachNewThreadSelector_toTarget_withObject:)exit,
runner, nil)
####

And here's some output from it:
2007-01-03 23:30:42.204 irb[4904] *** _NSAutoreleaseNoPool():
Object 0x54d020 of class NSInvocation autoreleased with no pool in
place - just leaking
2007-01-03 23:30:42.205 irb[4904] *** _NSAutoreleaseNoPool():
Object 0x54e7d0 of class NSCFDictionary autoreleased with no pool
in place - just leaking
2007-01-03 23:30:42.205 irb[4904] *** _NSAutoreleaseNoPool():
Object 0x54e200 of class RBObject autoreleased with no pool in
place - just leaking
2007-01-03 23:30:42.206 irb[4904] *** _NSAutoreleaseNoPool():
Object 0x54df40 of class NSCFString autoreleased with no pool in
place - just leaking
2007-01-03 23:30:42.206 irb[4904] *** _NSAutoreleaseNoPool():
Object 0x3060e0 of class NSCFString autoreleased with no pool in
place - just leaking
2007-01-03 23:30:42.207 irb[4904] *** _NSAutoreleaseNoPool():
Object 0x54df60 of class NSCFArray autoreleased with no pool in
place - just leaking
2007-01-03 23:30:42.207 irb[4904] *** _NSAutoreleaseNoPool():
Object 0x54e8b0 of class NSCFString autoreleased with no pool in
place - just leaking
2007-01-03 23:30:42.207 irb[4904] *** _NSAutoreleaseNoPool():
Object 0x54e9b0 of class NSCFString autoreleased with no pool in
place - just leaking
2007-01-03 23:30:42.208 irb[4904] *** _NSAutoreleaseNoPool():
Object 0x54e920 of class NSCFString autoreleased with no pool in
place - just leaking
2007-01-03 23:30:42.208 irb[4904] *** _NSAutoreleaseNoPool():
Object 0x54df70 of class NSCFString autoreleased with no pool in
place - just leaking
2007-01-03 23:30:42.208 irb[4904] *** _NSAutoreleaseNoPool():
Object 0x54ea30 of class NSCFString autoreleased with no pool in
place - just leaking
2007-01-03 23:30:42.208 irb[4904] *** _NSAutoreleaseNoPool():
Object 0x54f670 of class NSCFString autoreleased with no pool in
place - just leaking
2007-01-03 23:30:42.209 irb[4904] *** _NSAutoreleaseNoPool():
Object 0x54f6f0 of class NSCFString autoreleased with no pool in
place - just leaking
2007-01-03 23:30:42.209 irb[4904] *** _NSAutoreleaseNoPool():
Object 0x54df90 of class NSCFString autoreleased with no pool in
place - just leaking
2007-01-03 23:30:42.209 irb[4904] *** _NSAutoreleaseNoPool():
Object 0x54f7d0 of class NSCFString autoreleased with no pool in
place - just leaking
2007-01-03 23:30:42.210 irb[4904] *** _NSAutoreleaseNoPool():
Object 0x54f7b0 of class NSException autoreleased with no pool in
place - just leaking
2007-01-03 23:30:42.210 irb[4904] *** Uncaught exception:
<RBException_SystemExit> exit

Which isn't too hopeful.

Is this just a silly idea? Can anyone suggest what I'm doing wrong
(no doubt, quite a lot of things), or a better approach to this?

Cheers,
Benjohn
 
S

spooq

I'd like to be able to fire up the NSApplication's run loop from
within a new NSThread.

I can't comment on any Mac-specific code, but in my experience mixing
threading/event models rarely works. Things like select() get
confused.
 
B

benjohn

Spooq:
I can't comment on any Mac-specific code, but in my experience mixing
threading/event models rarely works. Things like select() get
confused.

I've realised two things.

First, I don't know what's going on - I'm reading the big Cocoa
Programming book by Scott Anguish et al, and it's helping. There's lots
about the cocoa / objective c run time interface at the back. I presume
this is how the Ruby Cocoa bridge works. Anyway, it's interesting, and
perhaps it'll help. I suspect that at least one problem is that the Ruby
interpreter is unlikely to be thread safe and re-entrant. Perhaps it is,
I don't know.

Second, starting a thread is just one approach. What I'm after is a
minimal way of:
* Getting the application loop going while also
* Continuing to have IRB interaction.

So I'll keep on working on that :)

Cheers,
Benjohn
 
S

spooq

Spooq:

I've realised two things.

First, I don't know what's going on - I'm reading the big Cocoa
Programming book by Scott Anguish et al, and it's helping. There's lots
about the cocoa / objective c run time interface at the back. I presume
this is how the Ruby Cocoa bridge works. Anyway, it's interesting, and
perhaps it'll help. I suspect that at least one problem is that the Ruby
interpreter is unlikely to be thread safe and re-entrant. Perhaps it is,
I don't know.

There are just so many ways and places it could be breaking, I would
try not to get involved with any of them :p
Second, starting a thread is just one approach. What I'm after is a
minimal way of:
* Getting the application loop going while also
* Continuing to have IRB interaction.

Perhaps you could invert the problem, and put a widget in your app
that allowed you to type in code and eval it? You could probably
emulate a terminal-style interface without much effort.
 
B

benjohn

Spooq:
Perhaps you could invert the problem, and put a widget in your app
that allowed you to type in code and eval it? You could probably
emulate a terminal-style interface without much effort.

It's a good plan and I definitely could do that. In fact, the original
inspiration to do this came from an article that followed your
suggestion. I don't want to do that however because it seems
restrictive.

My way round, I can have a re-usable component that you can "require",
that will give you an application run loop. If you happen to be using it
from IRB, you can continue to explore and poke about with the
application. You could also fire it up from a script, or have your unit
tests making use of it.

The other way round (your inverted suggestion), I've got a basic
application that includes a console. Unfortunately, I loose the tools
I'm used to having available from a terminal prompt, and I think it
would restrict using it from a finished script or from a unit test, etc.

I'm sure there's more to it than that, but I can't put my finger on it.
Or I'm just being stubborn :)

Cheers,
Benjohn
 
J

John Labovitz

The other way round (your inverted suggestion), I've got a basic
application that includes a console. Unfortunately, I loose the tools
I'm used to having available from a terminal prompt, and I think it
would restrict using it from a finished script or from a unit test,
etc.

This is just a wild guess, but I wonder whether you could use the
iTerm framework (http://sourceforge.net/projects/iterm/) to embed a
console in your app. I suppose (because I haven't tried it) that you
could instantiate a console using Ruby. It wouldn't really help in
IRB'ing your running Ruby app, but it might at least let you have a
real shell that you (or your users) would interact with, still inside
your app.

--John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top