Sending object between threads.

  • Hi,

    Following the example given in the Cocoa documentation "Forming
    Connections Between Threads", I have implemented a separate thread in
    my app to do some stuff, using NSConnection/NSPort to communicate
    between the main thread and the worker thread. It all works, except
    that I'm having trouble passing my own custom objects to and from the
    worker thread (so I can't actually get my worker to do any useful
    work!!). I can pass other cocoa objects (eg NSString) just fine, and
    they appear intact at the other side of the connection. If I pass my
    own object, I just get junk at the other end.

    Objects of my custom class conform to NSCoding, but my encodeWithCoder:
    and initWithCoder: methods never get called. Have I missed something
    obvious here, or is it more likely a dumb coding bug? I'm going round
    in circles reading the documentation, but can't see what I'm doing
    wrong. Can anyone suggest what I might have missed, or where I can go
    for further reading (better still, is there any sample code which does
    this - I couldn't find any?)

    Here's what my custom object looks like:

    @interface ChangerRequest : NSObject <NSCoding>
    {
      unsigned long    requestID;
      RequestType    type;
      BOOL        isRunning;
    }
    @end

    @implementation ChangerRequest

    - (id)init
    {
        requestID = INVALID_REQUEST_ID;
        isRunning = NO;

        return self;
    }

    - (void) encodeWithCoder: (NSCoder *)coder
    {
        [coder encodeValueOfObjCType: @encode (unsigned long) at:
    &requestID];
        [coder encodeValueOfObjCType: @encode (RequestType) at: &type];
        [coder encodeValueOfObjCType: @encode (BOOL) at: &isRunning];
    }

    - (id) initWithCoder: (NSCoder *)coder
    {
        // Must decode keys in same order as encodeWithCoder:
        [coder decodeValueOfObjCType: @encode (unsigned long) at:
    &requestID];
        [coder decodeValueOfObjCType: @encode (RequestType) at: &type];
        [coder decodeValueOfObjCType: @encode (BOOL) at: &isRunning];
        return self;
    }

    and my call to the worker thread looks like this:

        // Allocate and initialise a new request.
        ChangerRequest *theRequest = [[ChangerRequest alloc] init];
        [theRequest setCaller: (id)0x98765]; // Some junk just to see it
    working.
        [theRequest setType: fourth_type];

        [requests addObject: theRequest]; // maintain a list of outstanding
    requests.

        // Now send the request to the server to be actioned.
        [requestServer newRequestFromClient: theRequest];

    where requestServer was set up in method setServer (as described in the
    documentation), and the function newRequestFromClient is defined in a
    protocol as follows:-

    @protocol RequestHandlerServerMethods
    - (void) newRequestFromClient: (ChangerRequest *) theRequest;
    @end

    Any help very much appreciated,

    Terry Smyth
    SGL
    _______________________________________________
    cocoa-dev mailing list | <cocoa-dev...>
    Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    Do not post admin requests to the list. They will be ignored.
  • Although it's unrelated to your problem directly (encoding/decoding
    custom objects). If you are connecting a NSPort on a run loop and use a
    NSPortMessage to send data you can send pointers to in process memory
    locations without any problems. This is speedier than encoding/decoding
    the objects.

    Sounds like you have most everything you need in place but you should
    check out Nathan Day's example:

    http://homepage.mac.com/nathan_day

    Which is a really good general case implementation.

    I have done a specialized implementation for a background HTTP worker
    passing notification pointers based on that method:

    http://jrepp.com/cocoabb/viewtopic.php?t=64

    -jake

    -----Original Message-----
    From: Terry Smyth [mailto:<terry.smyth...>]
    Sent: Monday, January 20, 2003 9:51 AM
    To: <cocoa-dev...>
    Subject: Sending object between threads.

    Hi,

    Following the example given in the Cocoa documentation "Forming
    Connections Between Threads", I have implemented a separate thread in
    my app to do some stuff, using NSConnection/NSPort to communicate
    between the main thread and the worker thread. It all works, except
    that I'm having trouble passing my own custom objects to and from the
    worker thread (so I can't actually get my worker to do any useful
    work!!). I can pass other cocoa objects (eg NSString) just fine, and
    they appear intact at the other side of the connection. If I pass my
    own object, I just get junk at the other end.

    Objects of my custom class conform to NSCoding, but my encodeWithCoder:
    and initWithCoder: methods never get called. Have I missed something
    obvious here, or is it more likely a dumb coding bug? I'm going round
    in circles reading the documentation, but can't see what I'm doing
    wrong. Can anyone suggest what I might have missed, or where I can go
    for further reading (better still, is there any sample code which does
    this - I couldn't find any?)

    Here's what my custom object looks like:

    @interface ChangerRequest : NSObject <NSCoding>
    {
      unsigned long        requestID;
      RequestType  type;
      BOOL        isRunning;
    }
    @end

    @implementation ChangerRequest

    - (id)init
    {
        requestID = INVALID_REQUEST_ID;
        isRunning = NO;

        return self;
    }

    - (void) encodeWithCoder: (NSCoder *)coder
    {
        [coder encodeValueOfObjCType: @encode (unsigned long) at:
    &requestID];
        [coder encodeValueOfObjCType: @encode (RequestType) at: &type];
        [coder encodeValueOfObjCType: @encode (BOOL) at: &isRunning];
    }

    - (id) initWithCoder: (NSCoder *)coder
    {
        // Must decode keys in same order as encodeWithCoder:
        [coder decodeValueOfObjCType: @encode (unsigned long) at:
    &requestID];
        [coder decodeValueOfObjCType: @encode (RequestType) at: &type];
        [coder decodeValueOfObjCType: @encode (BOOL) at: &isRunning];
        return self;
    }

    and my call to the worker thread looks like this:

        // Allocate and initialise a new request.
        ChangerRequest *theRequest = [[ChangerRequest alloc] init];
        [theRequest setCaller: (id)0x98765]; // Some junk just to see it
    working.
        [theRequest setType: fourth_type];

        [requests addObject: theRequest]; // maintain a list of outstanding
    requests.

        // Now send the request to the server to be actioned.
        [requestServer newRequestFromClient: theRequest];

    where requestServer was set up in method setServer (as described in the
    documentation), and the function newRequestFromClient is defined in a
    protocol as follows:-

    @protocol RequestHandlerServerMethods
    - (void) newRequestFromClient: (ChangerRequest *) theRequest;
    @end

    Any help very much appreciated,

    Terry Smyth
    SGL
    _______________________________________________
    cocoa-dev mailing list | <cocoa-dev...>
    Help/Unsubscribe/Archives:
    http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    Do not post admin requests to the list. They will be ignored.
    _______________________________________________
    cocoa-dev mailing list | <cocoa-dev...>
    Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    Do not post admin requests to the list. They will be ignored.
  • Hi Terry!

    I also ran into this problem.
    The simplest way to solve that problem is to pass your
    object pointer castet to a uintptr_t.
    After received by the worker thread simply cast the
    pointer back.
    Make sure the object is still valid for the worker.
    Maybe you retain the object for the worker and the
    worker releases it.

    Hope that helps...
    Nico

    On Montag, Januar 20, 2003, at 07:05  Uhr, cocoa-dev-
    <request...> wrote:

    > Date: Mon, 20 Jan 2003 17:50:39 +0000
    > Subject: Sending object between threads.
    > From: Terry Smyth <terry.smyth...>
    > To: <cocoa-dev...>
    >
    > Hi,
    >
    > Following the example given in the Cocoa documentation "Forming
    > Connections Between Threads", I have implemented a separate thread in
    > my app to do some stuff, using NSConnection/NSPort to communicate
    > between the main thread and the worker thread. It all works, except
    > that I'm having trouble passing my own custom objects to and from the
    > worker thread (so I can't actually get my worker to do any useful
    > work!!). I can pass other cocoa objects (eg NSString) just fine, and
    > they appear intact at the other side of the connection. If I pass my
    > own object, I just get junk at the other end.
    >
    > Objects of my custom class conform to NSCoding, but my encodeWithCoder:
    > and initWithCoder: methods never get called. Have I missed something
    > obvious here, or is it more likely a dumb coding bug? I'm going round
    > in circles reading the documentation, but can't see what I'm doing
    > wrong. Can anyone suggest what I might have missed, or where I can go
    > for further reading (better still, is there any sample code which does
    > this - I couldn't find any?)
    _______________________________________________
    cocoa-dev mailing list | <cocoa-dev...>
    Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    Do not post admin requests to the list. They will be ignored.
  • Thanks Nico & Jake,

    That did the trick. By casting to a uintptr_t I can now see my object
    at the other end of the connection. Though I still don't understand why
    my objects are not getting encoded and transferred as I had expected
    (it seems at present just a pointer to the object is sent). This is
    fine for now while I am communicating between threads in the same app.
    Later, my worker thread will need to run on a separate machine, and I
    will need a full DO implementation - hopefully once I've done that, I
    will see my objects encoded and transferred across the connection.

    Thanks for your help,

    Terry

    On Tuesday, January 21, 2003, at 08:12  pm, Nico wrote:

    > Hi Terry!
    >
    > I also ran into this problem.
    > The simplest way to solve that problem is to pass your
    > object pointer castet to a uintptr_t.
    > After received by the worker thread simply cast the
    > pointer back.
    > Make sure the object is still valid for the worker.
    > Maybe you retain the object for the worker and the
    > worker releases it.
    >
    > Hope that helps...
    > Nico
    >
    > On Montag, Januar 20, 2003, at 07:05  Uhr, cocoa-dev-
    > <request...> wrote:
    >
    >> Date: Mon, 20 Jan 2003 17:50:39 +0000
    >> Subject: Sending object between threads.
    >> From: Terry Smyth <terry.smyth...>
    >> To: <cocoa-dev...>
    >>
    >> Hi,
    >>
    >> Following the example given in the Cocoa documentation "Forming
    >> Connections Between Threads", I have implemented a separate thread in
    >> my app to do some stuff, using NSConnection/NSPort to communicate
    >> between the main thread and the worker thread. It all works, except
    >> that I'm having trouble passing my own custom objects to and from the
    >> worker thread (so I can't actually get my worker to do any useful
    >> work!!). I can pass other cocoa objects (eg NSString) just fine, and
    >> they appear intact at the other side of the connection. If I pass my
    >> own object, I just get junk at the other end.
    >>
    >> Objects of my custom class conform to NSCoding, but my
    >> encodeWithCoder:
    >> and initWithCoder: methods never get called. Have I missed something
    >> obvious here, or is it more likely a dumb coding bug? I'm going round
    >> in circles reading the documentation, but can't see what I'm doing
    >> wrong. Can anyone suggest what I might have missed, or where I can go
    >> for further reading (better still, is there any sample code which does
    >> this - I couldn't find any?)
    _______________________________________________
    cocoa-dev mailing list | <cocoa-dev...>
    Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    Do not post admin requests to the list. They will be ignored.
  • Terry,

    You need to implement the NSCopying and NSCoding protocols on all the
    objects you want to pass. This will work within the same app or across
    apps - using real DO.
    Also remember if you pass the object pointer, like suggested before,
    you should use an NSLock to lock access to the object so that the 2
    threads do not access the object at the same time - if that happens the
    app will crash and this problem will be very hard to track later on.

    Regards,

    Jorge Monteiro
    http://www.jomosoft.com

    On Thursday, January 23, 2003, at 05:23 AM, Terry Smyth wrote:

    > Thanks Nico & Jake,
    >
    > That did the trick. By casting to a uintptr_t I can now see my object
    > at the other end of the connection. Though I still don't understand
    > why my objects are not getting encoded and transferred as I had
    > expected (it seems at present just a pointer to the object is sent).
    > This is fine for now while I am communicating between threads in the
    > same app. Later, my worker thread will need to run on a separate
    > machine, and I will need a full DO implementation - hopefully once
    > I've done that, I will see my objects encoded and transferred across
    > the connection.
    >
    > Thanks for your help,
    >
    > Terry
    >
    > On Tuesday, January 21, 2003, at 08:12  pm, Nico wrote:
    >
    >> Hi Terry!
    >>
    >> I also ran into this problem.
    >> The simplest way to solve that problem is to pass your
    >> object pointer castet to a uintptr_t.
    >> After received by the worker thread simply cast the
    >> pointer back.
    >> Make sure the object is still valid for the worker.
    >> Maybe you retain the object for the worker and the
    >> worker releases it.
    >>
    >> Hope that helps...
    >> Nico
    >>
    >> On Montag, Januar 20, 2003, at 07:05  Uhr, cocoa-dev-
    >> <request...> wrote:
    >>
    >>> Date: Mon, 20 Jan 2003 17:50:39 +0000
    >>> Subject: Sending object between threads.
    >>> From: Terry Smyth <terry.smyth...>
    >>> To: <cocoa-dev...>
    >>>
    >>> Hi,
    >>>
    >>> Following the example given in the Cocoa documentation "Forming
    >>> Connections Between Threads", I have implemented a separate thread in
    >>> my app to do some stuff, using NSConnection/NSPort to communicate
    >>> between the main thread and the worker thread. It all works, except
    >>> that I'm having trouble passing my own custom objects to and from the
    >>> worker thread (so I can't actually get my worker to do any useful
    >>> work!!). I can pass other cocoa objects (eg NSString) just fine, and
    >>> they appear intact at the other side of the connection. If I pass my
    >>> own object, I just get junk at the other end.
    >>>
    >>> Objects of my custom class conform to NSCoding, but my
    >>> encodeWithCoder:
    >>> and initWithCoder: methods never get called. Have I missed something
    >>> obvious here, or is it more likely a dumb coding bug? I'm going round
    >>> in circles reading the documentation, but can't see what I'm doing
    >>> wrong. Can anyone suggest what I might have missed, or where I can go
    >>> for further reading (better still, is there any sample code which
    >>> does
    >>> this - I couldn't find any?)
    > _______________________________________________
    > cocoa-dev mailing list | <cocoa-dev...>
    > Help/Unsubscribe/Archives:
    > http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    > Do not post admin requests to the list. They will be ignored.
    _______________________________________________
    cocoa-dev mailing list | <cocoa-dev...>
    Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
    Do not post admin requests to the list. They will be ignored.
previous month january 2003 next month
MTWTFSS
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
Go to today