summaryrefslogtreecommitdiff
path: root/objective-c/src/Ice/Dispatcher.mm
blob: a3a53fa9ac238df78c21cfca888a5c0ae3064227 (plain)
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// **********************************************************************
//
// Copyright (c) 2003-2015 ZeroC, Inc. All rights reserved.
//
// This copy of Ice is licensed to you under the terms described in the
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************

#import <DispatcherI.h>
#import <Util.h>
#import <ConnectionI.h>
#import <LocalObjectI.h>

#include <Block.h>

namespace
{

class DispatcherI : public Ice::Dispatcher
{
public:

// We must explicitely retain/release so that the garbage
// collector does not trash the dispatcher.
DispatcherI(void(^dispatcher)(id<ICEDispatcherCall>, id<ICEConnection>)) : _dispatcher(Block_copy(dispatcher))
{
}

virtual ~DispatcherI()
{
    Block_release(_dispatcher);
}

virtual void
dispatch(const Ice::DispatcherCallPtr& call, const Ice::ConnectionPtr& connection)
{
    NSException* ex = nil;
    @autoreleasepool
    {
        id<ICEConnection> con = [ICEConnection localObjectWithCxxObject:connection.get()];
        id<ICEDispatcherCall> c = [[ICEDispatcherCall alloc] initWithCall:call.get()];
        @try
        {
            _dispatcher(c, con);
        }
        @catch(id e)
        {
            ex = [e retain];
        }
        @finally
        {
            [c release];
        }
    }
    if(ex != nil)
    {
        rethrowCxxException(ex, true); // True = release the exception.
    }
}

private:

void(^_dispatcher)(id<ICEDispatcherCall>, id<ICEConnection>);

};
typedef IceUtil::Handle<DispatcherI> DispatcherIPtr;

}

@implementation ICEDispatcher
+(Ice::Dispatcher*) dispatcherWithDispatcher:(void(^)(id<ICEDispatcherCall>, id<ICEConnection>))dispatcher
{
    return new DispatcherI(dispatcher);
}
@end

@implementation ICEDispatcherCall
-(id) initWithCall:(Ice::DispatcherCall*)call
{
    self = [super init];
    if(!self)
    {
        return nil;
    }

    cxxCall_ = call;
    cxxCall_->__incRef();
    return self;
}
-(void) dealloc
{
    cxxCall_->__decRef();
    cxxCall_ = 0;
    [super dealloc];
}
-(void) run
{
    cppCall(^ { cxxCall_->run(); });
}
@end