Thread View: comp.sys.next.programmer
1 messages
1 total messages
Started by Matthew Dillon
Mon, 07 Sep 1992 22:25
NS3.0 Distributed objects questions / example code
Author: Matthew Dillon
Date: Mon, 07 Sep 1992 22:25
Date: Mon, 07 Sep 1992 22:25
386 lines
11177 bytes
11177 bytes
This documentation is *AWEFUL*!! You get little one paragraph
descriptions that tell you very little about how things are supposed to
work. There were only 3 examples in the NeXT supplied documentation
for distributed objects and the one I was interested in --
multi-threading on the server side, is broken (it leaves threads lying
around after the client exits).
If anyone has any idea re: the following I would greatly appreciate an
answer. Please post answers to the net!
Goal:
I have a server process which registers a named
NXConnection. I have N client processes which wish
to connect to this server process.
I want the server to SILENTLY fork off a thread for each client
that connects to it.
Problems:
Currently this does not seem possible without writing a bandaid
called 'newThread' which the client must then call. Unfortunately,
this bandaid not only requires the client to KNOW that the server
is doing something wierd (it should be invisible), but also causes
the server to call its - connection method whenever any method is
called using the original proxy.
(1) The - connection method is described in all of one paragraph
in the NeXT documentation. It does not give you any hint
on how the arguments are supposed to be used and how the
returned connection is interpreted.
In example program #1 below the - connection method is called
just once for each client no matter how many operations that
client performs on its proxy. This works as expected
(2) Normally the inPort for a new connection <newConn> is the same
as the inPort for the registration <conn>, meaning that you
cannot fork off a thread to handle that connection because all
the threads will try to read data from the same port. That
is, you want a particular thread to process a particular
connection and no other.
So, in example #2 I tried to use connectToPort:withInPort: to
setup a separate inPort for the connection then run said
connection in a new thread. Unfortunately, this didn't work
big time:
(a) The - connection method on the server is run EACH TIME
the client calls a method in its original proxy object (it
didn't do this in example #1!!). This appears to be due to my
returning something other then <conn> in the - connection
method.
(b) Further, the client's proxy does not appear to access the
new port.
(c) If the client then calls the - newThread method it
obtains a new proxy object which DOES appear to use the
proper connection (the one that I tried to setup and fork
off to a separate thread). This is the bandaid, but has
bad side effects as I described above.
(3) registerForInvalidationNotification does not appear to work
at all. It does not work with the NeXT provided examples.
When a client exits the server is never notified and the now
defunct thread sticks around. (example program #2)
use 'ps m' to list the threads
I don't want alienate NeXT but I gotta say that you guys (NeXT people)
MUST provide more SELF CONTAINED (i.e. compilable) examples to
demonstrate all the quirks your documentation doesn't talk about. It
took me ALL DAY to just get as far as I did and half of what I learned
isn't covered in any documentation anywhere. The only thing of any use
are the few examples in Examples/ ... most of the examples embedded in
the documentation are totally useless because they assume you
understand the 10,000 items that had to be setup before the particular
lines shown in the example. That's no example!
Any Netter's out there who've figured this out would have my undying
thanks if they posted the solution to the net!
Thanks,
-Matt
------------------------------- CUT HERE ---------------------------
/*
* MTHREAD1.C
*
* Modified from developer examples
*
* A simple multi-threaded example
*/
#import <objc/Object.h>
#import <remote/NXConnection.h>
#import <remote/NXProxy.h>
#import <mach/cthreads.h>
#import <machkit/NXPort.h>
#import <machkit/senderIsInvalid.h>
/*
* Our protocol
*/
@protocol ServerProtocol
- newThread;
- (int) doWork;
@end
/*
* Our object class which uses the protocol
*/
@interface MTS : Object <ServerProtocol, NXSenderIsInvalid>
@end
/*
* Our implementation
*/
@implementation MTS
/*
* Method called when a client connects to us. connect provides us
* with <conn>, a connection which shares topConn's input port and
* has its own output port. The associated object is <self> (i.e. the
* one we registered with the name sever)
*
* connection in this case is only called once
*/
- connection: (NXConnection *)topConn didConnect:(NXConnection *)conn {
printf("connect\n");
[conn registerForInvalidationNotification:self];
return(conn);
}
- senderIsInvalid: sender
{
puts("died!");
}
- newThread {
puts("new thread");
return self;
}
- (int) doWork {
puts("do work");
return (int) cthread_self();
}
@end
/*
* Run the program twice... the first process will be the server, the second
* will be the client (the third will be a client, etc...)
*/
main()
{
id hub; // proxy object (client) or server object
hub = [NXConnection connectToName:"MTS example"];
printf("I am %d\n", cthread_self());
objc_setMultithreaded(YES);
if (hub) {
id core; // object to handle invalidation notification
id sub;
short i;
/*
* We are a client, <hub> is our proxy. Create <core> to handle
* invalidation notifcation since we can't use <hub>
*/
core = [[MTS alloc] init];
[[hub connectionForProxy] registerForInvalidationNotification:core];
[hub setProtocolForProxy:@protocol(ServerProtocol)];
puts("client connect");
printf("dowork is %d\n", [hub doWork]);
printf("dowork is %d\n", [hub doWork]);
printf("dowork is %d\n", [hub doWork]);
printf("newThread is %08lx\n", [hub newThread]);
printf("newThread is %08lx\n", [hub newThread]);
printf("newThread is %08lx\n", [hub newThread]);
} else {
id topConn; // our server connection
/*
* Make us a server, create hub and register for invalidation
* notification
*/
hub = [MTS new];
printf("self is %08lx\n", hub);
topConn = [NXConnection registerRoot:hub withName:"MTS example"];
[topConn registerForInvalidationNotification:hub];
puts("server wait");
[topConn setDelegate:hub]; // so hub gets connection msg
[topConn run];
}
return(0);
}
------------------------------- CUT HERE ---------------------------
/*
* MTHREAD2.C
*
* Modified from developer examples
*
* A simple multi-threaded example, Each new client gets a dedicated
* thread.
*/
#import <objc/Object.h>
#import <remote/NXConnection.h>
#import <remote/NXProxy.h>
#import <mach/cthreads.h>
#import <machkit/NXPort.h>
#import <machkit/senderIsInvalid.h>
/*
* Our protocol
*/
@protocol ServerProtocol
- newThread;
- (int) doWork;
@end
/*
* Our object class which uses the protocol
*/
@interface MTS : Object <ServerProtocol, NXSenderIsInvalid>
@end
/*
* Our implementation
*/
@implementation MTS
/*
* Connections are handled by the main thread only. Note that the
* inPort for the proxy object obtained by the client works under
* the 'third party server' paradigm, meaning that each accesses to
* it is a connection. This occurs even if the 'server' is the same
* machine as the program which posted the named port.
*
* topConn is the server place holder, conn is an instance connection. Note
* that conn may/will have the same inPort as topConn. Therefore, we cannot
* simply [conn runInNewThread] because it will compete with the main
* thread for data.
*/
- connection: (NXConnection *)topConn didConnect:(NXConnection *)conn {
id threadConn;
id proxy;
id inPort = [NXPort new];
id mts = [MTS new];
puts("connect");
proxy = [NXConnection connectToPort:[conn outPort] withInPort:inPort];
threadConn = [proxy connectionForProxy];
[conn free];
[threadConn registerForInvalidationNotification:mts];
[threadConn runInNewThread];
[threadConn setRoot:mts];
return (threadConn);
}
- senderIsInvalid: sender
{
printf("Sender %08lx died!\n", sender);
write(1, "XXX\n", 4);
}
/*
*
*/
- newThread {
printf("New Thread %08lx %d\n", self, cthread_self());
return self;
}
- (int) doWork {
printf("DoWork: %08lx %d\n", self, cthread_self());
return (int) cthread_self();
}
@end
/*
* Run the program twice... the first process will be the server, the second
* will be a client.
*/
main()
{
id hub; // proxy object (client) or server object
hub = [NXConnection connectToName:"MTS example"];
printf("I am %d\n", cthread_self());
objc_setMultithreaded(YES);
if (hub) {
id core; // object to handle invalidation notification
id sub;
short i;
/*
* We are a client, <hub> is our proxy. Create <core> to handle
* invalidation notifcation since we can't use <hub>
*/
core = [[MTS alloc] init];
[[hub connectionForProxy] registerForInvalidationNotification:core];
[hub setProtocolForProxy:@protocol(ServerProtocol)];
puts("client connect");
for (i = 0; i < 5; ++i) {
sleep(1);
printf("test-doWork %d\n", [hub doWork]);
}
sub = [hub newThread];
for (i = 0; i < 5; ++i) {
sleep(1);
printf("sub %d: %d\n", i, [sub doWork]);
}
for (i = 0; i < 5; ++i) {
sleep(1);
printf("test-doWork %d\n", [hub doWork]);
}
sub = [hub newThread];
for (i = 0; i < 5; ++i) {
sleep(1);
printf("sub %d: %d\n", i, [sub doWork]);
}
} else {
id topConn; // our server connection
/*
* Make us a server, create hub and register for invalidation
* notification
*/
hub = [MTS new];
printf("self is %08lx\n", hub);
topConn = [NXConnection registerRoot:hub withName:"MTS example"];
[topConn registerForInvalidationNotification:hub];
puts("server wait");
[topConn setDelegate:hub]; // so hub gets connection msg
[topConn run];
}
return(0);
}
------------------------------- CUT HERE ---------------------------
--
Matthew Dillon dillon@Overload.Berkeley.CA.US
891 Regal Rd. uunet.uu.net!overload!dillon
Berkeley, Ca. 94708 ham: KC6LVW (no mail drop)
USA Sandel-Avery Engineering (702)831-8000
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads