summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2015-03-20 18:18:03 +0100
committerBenoit Foucher <benoit@zeroc.com>2015-03-20 18:18:03 +0100
commitc6133370d229578697c157f94b297dcc593b4a5f (patch)
tree9bbc2e3083338315393109a511e7a65d09dc9ac6 /cpp/src
parentRemove src directory. (diff)
downloadice-c6133370d229578697c157f94b297dcc593b4a5f.tar.bz2
ice-c6133370d229578697c157f94b297dcc593b4a5f.tar.xz
ice-c6133370d229578697c157f94b297dcc593b4a5f.zip
Added iOS support for IceTouch
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/Ice/ConnectionFactory.cpp83
-rw-r--r--cpp/src/Ice/ConnectionFactory.h9
-rw-r--r--cpp/src/Ice/ConnectionI.h4
-rw-r--r--cpp/src/Ice/EventHandler.h3
-rw-r--r--cpp/src/Ice/Exception.cpp9
-rw-r--r--cpp/src/Ice/Network.h8
-rw-r--r--cpp/src/Ice/PropertyNames.cpp3
-rw-r--r--cpp/src/Ice/PropertyNames.h2
-rw-r--r--cpp/src/Ice/Selector.cpp479
-rw-r--r--cpp/src/Ice/Selector.h129
-rw-r--r--cpp/src/slice2cpp/Gen.cpp2
-rw-r--r--cpp/src/slice2cpp/Main.cpp2
-rw-r--r--cpp/src/slice2objc/Gen.cpp2
-rw-r--r--cpp/src/slice2objc/Main.cpp2
14 files changed, 729 insertions, 8 deletions
diff --git a/cpp/src/Ice/ConnectionFactory.cpp b/cpp/src/Ice/ConnectionFactory.cpp
index cfcef92d9bc..ec04336d76c 100644
--- a/cpp/src/Ice/ConnectionFactory.cpp
+++ b/cpp/src/Ice/ConnectionFactory.cpp
@@ -28,6 +28,16 @@
#include <IceUtil/Random.h>
#include <iterator>
+#if TARGET_OS_IPHONE != 0
+namespace IceInternal
+{
+
+bool registerForBackgroundNotification(IceInternal::IncomingConnectionFactory*);
+void unregisterForBackgroundNotification(IceInternal::IncomingConnectionFactory*);
+
+}
+#endif
+
using namespace std;
using namespace Ice;
using namespace Ice::Instrumentation;
@@ -1361,6 +1371,23 @@ void
IceInternal::IncomingConnectionFactory::finished(ThreadPoolCurrent&, bool close)
{
IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
+
+#if TARGET_OS_IPHONE != 0
+ if(_state < StateClosed)
+ {
+ //
+ // Finished has been called by stopAcceptor if the state isn't
+ // closed.
+ //
+ if(_acceptorStarted && close)
+ {
+ _acceptorStarted = false;
+ closeAcceptor();
+ }
+ return;
+ }
+#endif
+
assert(_state == StateClosed);
setState(StateFinished);
@@ -1368,6 +1395,11 @@ IceInternal::IncomingConnectionFactory::finished(ThreadPoolCurrent&, bool close)
{
closeAcceptor();
}
+
+#if TARGET_OS_IPHONE != 0
+ sync.release();
+ unregisterForBackgroundNotification(this);
+#endif
}
string
@@ -1441,6 +1473,48 @@ IceInternal::IncomingConnectionFactory::IncomingConnectionFactory(const Instance
{
}
+#if TARGET_OS_IPHONE != 0
+void
+IceInternal::IncomingConnectionFactory::startAcceptor()
+{
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
+ if(_state >= StateClosed || _acceptorStarted)
+ {
+ return;
+ }
+
+ try
+ {
+ createAcceptor();
+ _acceptorStarted = true;
+ }
+ catch(const Ice::Exception& ex)
+ {
+ if(_warn)
+ {
+ Warning out(_instance->initializationData().logger);
+ out << "unable to create acceptor:\n" << ex;
+ }
+ }
+}
+
+void
+IceInternal::IncomingConnectionFactory::stopAcceptor()
+{
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
+ if(_state >= StateClosed || !_acceptorStarted)
+ {
+ return;
+ }
+
+ if(_adapter->getThreadPool()->finish(this, true))
+ {
+ _acceptorStarted = false;
+ closeAcceptor();
+ }
+}
+#endif
+
void
IceInternal::IncomingConnectionFactory::initialize()
{
@@ -1473,7 +1547,16 @@ IceInternal::IncomingConnectionFactory::initialize()
}
else
{
+#if TARGET_OS_IPHONE != 0
+ //
+ // The notification center will call back on the factory to
+ // start the acceptor if necessary.
+ //
+ _acceptorStarted = false;
+ registerForBackgroundNotification(this);
+#else
createAcceptor();
+#endif
}
}
catch(const Ice::Exception&)
diff --git a/cpp/src/Ice/ConnectionFactory.h b/cpp/src/Ice/ConnectionFactory.h
index b6429b80e7f..bf211972ec8 100644
--- a/cpp/src/Ice/ConnectionFactory.h
+++ b/cpp/src/Ice/ConnectionFactory.h
@@ -170,6 +170,11 @@ public:
void hold();
void destroy();
+#if TARGET_OS_IPHONE != 0
+ void startAcceptor();
+ void stopAcceptor();
+#endif
+
void updateConnectionObservers();
void waitUntilHolding() const;
@@ -223,6 +228,10 @@ private:
const TransceiverPtr _transceiver;
EndpointIPtr _endpoint;
+#if TARGET_OS_IPHONE != 0
+ bool _acceptorStarted;
+#endif
+
Ice::ObjectAdapterIPtr _adapter;
const bool _warn;
diff --git a/cpp/src/Ice/ConnectionI.h b/cpp/src/Ice/ConnectionI.h
index aeedf315342..fdb80901122 100644
--- a/cpp/src/Ice/ConnectionI.h
+++ b/cpp/src/Ice/ConnectionI.h
@@ -41,7 +41,7 @@
#include <deque>
-#if !defined(ICE_OS_WINRT)
+#if TARGET_OS_IPHONE == 0 && !defined(ICE_OS_WINRT)
# ifndef ICE_HAS_BZIP2
# define ICE_HAS_BZIP2
# endif
@@ -275,9 +275,11 @@ private:
void doCompress(IceInternal::BasicStream&, IceInternal::BasicStream&);
void doUncompress(IceInternal::BasicStream&, IceInternal::BasicStream&);
#endif
+
IceInternal::SocketOperation parseMessage(IceInternal::BasicStream&, Int&, Int&, Byte&,
IceInternal::ServantManagerPtr&, ObjectAdapterPtr&,
IceInternal::OutgoingAsyncBasePtr&, ConnectionCallbackPtr&, int&);
+
void invokeAll(IceInternal::BasicStream&, Int, Int, Byte,
const IceInternal::ServantManagerPtr&, const ObjectAdapterPtr&);
diff --git a/cpp/src/Ice/EventHandler.h b/cpp/src/Ice/EventHandler.h
index 8ae656a0859..afbd608b961 100644
--- a/cpp/src/Ice/EventHandler.h
+++ b/cpp/src/Ice/EventHandler.h
@@ -71,6 +71,9 @@ protected:
friend class ThreadPool;
friend class ThreadPoolCurrent;
friend class Selector;
+#ifdef ICE_USE_CFSTREAM
+ friend class EventHandlerWrapper;
+#endif
};
}
diff --git a/cpp/src/Ice/Exception.cpp b/cpp/src/Ice/Exception.cpp
index 2b1015a5d7b..16c3a3addaa 100644
--- a/cpp/src/Ice/Exception.cpp
+++ b/cpp/src/Ice/Exception.cpp
@@ -830,3 +830,12 @@ Ice::ResponseSentException::ice_print(ostream& out) const
Exception::ice_print(out);
out << ":\nresponse sent exception";
}
+
+#ifdef ICE_USE_CFSTREAM
+void
+Ice::CFNetworkException::ice_print(ostream& out) const
+{
+ Exception::ice_print(out);
+ out << ":\nnetwork exception: domain: " << domain << " error: " << error;
+}
+#endif
diff --git a/cpp/src/Ice/Network.h b/cpp/src/Ice/Network.h
index a731a49db3d..f90e3d6da61 100644
--- a/cpp/src/Ice/Network.h
+++ b/cpp/src/Ice/Network.h
@@ -45,8 +45,10 @@ typedef int ssize_t;
#if defined(__linux) && !defined(ICE_NO_EPOLL)
# define ICE_USE_EPOLL 1
-#elif (defined(__APPLE__) || defined(__FreeBSD__)) && !defined(ICE_NO_KQUEUE)
+#elif (defined(__APPLE__) || defined(__FreeBSD__)) && TARGET_OS_IPHONE == 0 && !defined(ICE_NO_KQUEUE)
# define ICE_USE_KQUEUE 1
+#elif defined(__APPLE__) && !defined(ICE_NO_CFSTREAM)
+# define ICE_USE_CFSTREAM 1
#elif defined(_WIN32)
# if defined(ICE_OS_WINRT)
# elif !defined(ICE_NO_IOCP)
@@ -142,7 +144,11 @@ enum SocketOperation
// With BSD sockets, write and connect readiness are the same so
// we use the same value for both.
SocketOperationWrite = 2,
+#ifdef ICE_USE_CFSTREAM
+ SocketOperationConnect = 4
+#else
SocketOperationConnect = 2
+#endif
};
//
diff --git a/cpp/src/Ice/PropertyNames.cpp b/cpp/src/Ice/PropertyNames.cpp
index 3bcf9effd32..95cf61169a8 100644
--- a/cpp/src/Ice/PropertyNames.cpp
+++ b/cpp/src/Ice/PropertyNames.cpp
@@ -6,7 +6,7 @@
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
-// Generated by makeprops.py from file ../config/PropertyNames.xml, Tue Dec 9 12:08:30 2014
+// Generated by makeprops.py from file ./config/PropertyNames.xml, Thu Mar 19 17:54:51 2015
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
@@ -186,6 +186,7 @@ const IceInternal::Property IcePropsData[] =
IceInternal::Property("Ice.Warn.UnusedProperties", false, 0),
IceInternal::Property("Ice.CacheMessageBuffers", false, 0),
IceInternal::Property("Ice.ThreadInterruptSafe", false, 0),
+ IceInternal::Property("Ice.Voip", false, 0),
};
const IceInternal::PropertyArray
diff --git a/cpp/src/Ice/PropertyNames.h b/cpp/src/Ice/PropertyNames.h
index 37b0a8ee4e4..28b47265af6 100644
--- a/cpp/src/Ice/PropertyNames.h
+++ b/cpp/src/Ice/PropertyNames.h
@@ -6,7 +6,7 @@
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
-// Generated by makeprops.py from file ../config/PropertyNames.xml, Tue Dec 9 12:08:30 2014
+// Generated by makeprops.py from file ./config/PropertyNames.xml, Thu Mar 19 17:54:51 2015
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
diff --git a/cpp/src/Ice/Selector.cpp b/cpp/src/Ice/Selector.cpp
index 07f755276cb..39f411fb115 100644
--- a/cpp/src/Ice/Selector.cpp
+++ b/cpp/src/Ice/Selector.cpp
@@ -14,6 +14,11 @@
#include <Ice/LocalException.h>
#include <IceUtil/Time.h>
+#ifdef ICE_USE_CFSTREAM
+# include <CoreFoundation/CoreFoundation.h>
+# include <CoreFoundation/CFStream.h>
+#endif
+
using namespace std;
using namespace IceInternal;
@@ -519,6 +524,480 @@ Selector::select(vector<pair<EventHandler*, SocketOperation> >& handlers, int ti
}
}
+#elif defined(ICE_USE_CFSTREAM)
+
+namespace
+{
+
+void selectorInterrupt(void* info)
+{
+ reinterpret_cast<Selector*>(info)->processInterrupt();
+}
+
+void eventHandlerSocketCallback(CFSocketRef, CFSocketCallBackType callbackType, CFDataRef, const void* d, void* info)
+{
+ if(callbackType == kCFSocketReadCallBack)
+ {
+ reinterpret_cast<EventHandlerWrapper*>(info)->readyCallback(SocketOperationRead);
+ }
+ else if(callbackType == kCFSocketWriteCallBack)
+ {
+ reinterpret_cast<EventHandlerWrapper*>(info)->readyCallback(SocketOperationWrite);
+ }
+ else if(callbackType == kCFSocketConnectCallBack)
+ {
+ reinterpret_cast<EventHandlerWrapper*>(info)->readyCallback(SocketOperationConnect,
+ d ? *reinterpret_cast<const SInt32*>(d) : 0);
+ }
+}
+
+class SelectorHelperThread : public IceUtil::Thread
+{
+public:
+
+ SelectorHelperThread(Selector& selector) : _selector(selector)
+ {
+ }
+
+ virtual void run()
+ {
+ _selector.run();
+ }
+
+private:
+
+ Selector& _selector;
+};
+
+CFOptionFlags
+toCFCallbacks(SocketOperation op)
+{
+ CFOptionFlags cbs = 0;
+ if(op & SocketOperationRead)
+ {
+ cbs |= kCFSocketReadCallBack;
+ }
+ if(op & SocketOperationWrite)
+ {
+ cbs |= kCFSocketWriteCallBack;
+ }
+ if(op & SocketOperationConnect)
+ {
+ cbs |= kCFSocketConnectCallBack;
+ }
+ return cbs;
+}
+
+}
+
+EventHandlerWrapper::EventHandlerWrapper(const EventHandlerPtr& handler, Selector& selector) :
+ _handler(handler),
+ _nativeInfo(StreamNativeInfoPtr::dynamicCast(handler->getNativeInfo())),
+ _selector(selector),
+ _ready(SocketOperationNone),
+ _finish(false)
+{
+ if(!StreamNativeInfoPtr::dynamicCast(handler->getNativeInfo()))
+ {
+ SOCKET fd = handler->getNativeInfo()->fd();
+ CFSocketContext ctx = { 0, this, 0, 0, 0 };
+ _socket = CFSocketCreateWithNative(kCFAllocatorDefault,
+ fd,
+ kCFSocketReadCallBack |
+ kCFSocketWriteCallBack |
+ kCFSocketConnectCallBack,
+ eventHandlerSocketCallback,
+ &ctx);
+
+ // Disable automatic re-enabling of callbacks and closing of the native socket.
+ CFSocketSetSocketFlags(_socket, 0);
+ CFSocketDisableCallBacks(_socket, kCFSocketReadCallBack | kCFSocketWriteCallBack | kCFSocketConnectCallBack);
+ _source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, _socket, 0);
+ }
+ else
+ {
+ _socket = 0;
+ _source = 0;
+ _nativeInfo->initStreams(this);
+ }
+}
+
+EventHandlerWrapper::~EventHandlerWrapper()
+{
+ if(_socket)
+ {
+ CFRelease(_socket);
+ CFRelease(_source);
+ }
+}
+
+void
+EventHandlerWrapper::updateRunLoop()
+{
+ SocketOperation op = _handler->_registered;
+ assert(!op || !_finish);
+
+ if(_socket)
+ {
+ CFSocketDisableCallBacks(_socket, kCFSocketReadCallBack | kCFSocketWriteCallBack | kCFSocketConnectCallBack);
+ if(op)
+ {
+ CFSocketEnableCallBacks(_socket, toCFCallbacks(op));
+ }
+
+ if(op && !CFRunLoopContainsSource(CFRunLoopGetCurrent(), _source, kCFRunLoopDefaultMode))
+ {
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), _source, kCFRunLoopDefaultMode);
+ }
+ else if(!op && CFRunLoopContainsSource(CFRunLoopGetCurrent(), _source, kCFRunLoopDefaultMode))
+ {
+ CFRunLoopRemoveSource(CFRunLoopGetCurrent(), _source, kCFRunLoopDefaultMode);
+ }
+
+ if(_finish)
+ {
+ CFSocketInvalidate(_socket);
+ }
+ }
+ else
+ {
+ SocketOperation readyOp = _nativeInfo->registerWithRunLoop(op);
+ if(!(op & (SocketOperationWrite | SocketOperationConnect)) || _ready & SocketOperationWrite)
+ {
+ _nativeInfo->unregisterFromRunLoop(SocketOperationWrite, false);
+ }
+
+ if(!(op & (SocketOperationRead | SocketOperationConnect)) || _ready & SocketOperationRead)
+ {
+ _nativeInfo->unregisterFromRunLoop(SocketOperationRead, false);
+ }
+
+ if(readyOp)
+ {
+ ready(readyOp, 0);
+ }
+
+ if(_finish)
+ {
+ _nativeInfo->closeStreams();
+ }
+ }
+}
+
+void
+EventHandlerWrapper::readyCallback(SocketOperation op, int error)
+{
+ _selector.ready(this, op, error);
+}
+
+void
+EventHandlerWrapper::ready(SocketOperation op, int error)
+{
+ if(!_socket)
+ {
+ //
+ // Unregister the stream from the runloop as soon as we got the callback. This is
+ // required to allow thread pool thread to perform read/write operations on the
+ // stream (which can't be used from another thread than the run loop thread if
+ // it's registered with a run loop).
+ //
+ op = _nativeInfo->unregisterFromRunLoop(op, error != 0);
+ }
+
+ op = static_cast<SocketOperation>(_handler->_registered & op);
+ if(!op || _ready & op)
+ {
+ return;
+ }
+
+ if(_socket)
+ {
+ if(op & SocketOperationConnect)
+ {
+ _nativeInfo->setConnectError(error);
+ }
+ }
+
+ _ready = static_cast<SocketOperation>(_ready | op);
+ if(!(_handler->_disabled & op))
+ {
+ _selector.addReadyHandler(this);
+ }
+}
+
+void
+EventHandlerWrapper::checkReady()
+{
+ if(_ready & _handler->_registered)
+ {
+ _selector.addReadyHandler(this);
+ }
+}
+
+SocketOperation
+EventHandlerWrapper::readyOp()
+{
+ assert(!(~_handler->_registered & _ready));
+ SocketOperation op = static_cast<SocketOperation>(~_handler->_disabled & _ready);
+ _ready = static_cast<SocketOperation>(~op & _ready);
+ return op;
+}
+
+bool
+EventHandlerWrapper::update(SocketOperation remove, SocketOperation add)
+{
+ SocketOperation previous = _handler->_registered;
+ _handler->_registered = static_cast<SocketOperation>(_handler->_registered & ~remove);
+ _handler->_registered = static_cast<SocketOperation>(_handler->_registered | add);
+ if(previous == _handler->_registered)
+ {
+ return false;
+ }
+
+ // Clear ready flags which might not be valid anymore.
+ _ready = static_cast<SocketOperation>(_ready & _handler->_registered);
+ return true;
+}
+
+void
+EventHandlerWrapper::finish()
+{
+ _finish = true;
+ _ready = SocketOperationNone;
+ _handler->_registered = SocketOperationNone;
+}
+
+Selector::Selector(const InstancePtr& instance) : _instance(instance), _destroyed(false)
+{
+ CFRunLoopSourceContext ctx;
+ memset(&ctx, 0, sizeof(CFRunLoopSourceContext));
+ ctx.info = this;
+ ctx.perform = selectorInterrupt;
+ _source = CFRunLoopSourceCreate(0, 0, &ctx);
+ _runLoop = 0;
+
+ _thread = new SelectorHelperThread(*this);
+ _thread->start();
+
+ Lock sync(*this);
+ while(!_runLoop)
+ {
+ wait();
+ }
+}
+
+Selector::~Selector()
+{
+}
+
+void
+Selector::destroy()
+{
+ Lock sync(*this);
+
+ //
+ // Make sure any pending changes are processed to ensure remaining
+ // streams/sockets are closed.
+ //
+ _destroyed = true;
+ while(!_changes.empty())
+ {
+ CFRunLoopSourceSignal(_source);
+ CFRunLoopWakeUp(_runLoop);
+
+ wait();
+ }
+
+ _thread->getThreadControl().join();
+ _thread = 0;
+
+ CFRelease(_source);
+
+ assert(_wrappers.empty());
+ _readyHandlers.clear();
+ _selectedHandlers.clear();
+}
+
+void
+Selector::initialize(EventHandler* handler)
+{
+ Lock sync(*this);
+ _wrappers[handler] = new EventHandlerWrapper(handler, *this);
+}
+
+void
+Selector::update(EventHandler* handler, SocketOperation remove, SocketOperation add)
+{
+ Lock sync(*this);
+ const EventHandlerWrapperPtr& wrapper = _wrappers[handler];
+ assert(wrapper);
+ if(wrapper->update(remove, add))
+ {
+ _changes.insert(wrapper);
+ notify();
+ }
+}
+
+void
+Selector::enable(EventHandler* handler, SocketOperation op)
+{
+ Lock sync(*this);
+ if(!(handler->_disabled & op))
+ {
+ return;
+ }
+ handler->_disabled = static_cast<SocketOperation>(handler->_disabled & ~op);
+
+ if(handler->_registered & op)
+ {
+ _wrappers[handler]->checkReady();
+ }
+}
+
+void
+Selector::disable(EventHandler* handler, SocketOperation op)
+{
+ Lock sync(*this);
+ if(handler->_disabled & op)
+ {
+ return;
+ }
+ handler->_disabled = static_cast<SocketOperation>(handler->_disabled | op);
+}
+
+bool
+Selector::finish(EventHandler* handler, bool closeNow)
+{
+ Lock sync(*this);
+ std::map<EventHandler*, EventHandlerWrapperPtr>::iterator p = _wrappers.find(handler);
+ assert(p != _wrappers.end());
+ EventHandlerWrapperPtr wrapper = p->second;
+ wrapper->finish();
+ _wrappers.erase(p);
+ _changes.insert(wrapper);
+ notify();
+ return closeNow;
+}
+
+void
+Selector::select(std::vector<std::pair<EventHandler*, SocketOperation> >& handlers, int timeout)
+{
+ Lock sync(*this);
+
+ //
+ // Re-enable callbacks for previously selected handlers.
+ //
+ if(!_selectedHandlers.empty())
+ {
+ vector<pair<EventHandlerWrapperPtr, SocketOperation> >::const_iterator p;
+ for(p = _selectedHandlers.begin(); p != _selectedHandlers.end(); ++p)
+ {
+ if(!p->first->_finish)
+ {
+ _changes.insert(p->first);
+ }
+ }
+ _selectedHandlers.clear();
+ }
+
+ //
+ // Wait for handlers to be ready.
+ //
+ handlers.clear();
+ while(_selectedHandlers.empty())
+ {
+ while(!_changes.empty())
+ {
+ CFRunLoopSourceSignal(_source);
+ CFRunLoopWakeUp(_runLoop);
+
+ wait();
+ }
+
+ if(_readyHandlers.empty())
+ {
+ if(timeout > 0)
+ {
+ if(!timedWait(IceUtil::Time::seconds(timeout)))
+ {
+ break;
+ }
+ }
+ else
+ {
+ wait();
+ }
+ }
+
+ if(!_changes.empty())
+ {
+ continue; // Make sure to process the changes first.
+ }
+
+ for(vector<EventHandlerWrapperPtr>::const_iterator p = _readyHandlers.begin(); p != _readyHandlers.end(); ++p)
+ {
+ SocketOperation op = (*p)->readyOp();
+ if(op)
+ {
+ _selectedHandlers.push_back(pair<EventHandlerWrapperPtr, SocketOperation>(*p, op));
+ handlers.push_back(pair<EventHandler*, SocketOperation>((*p)->_handler.get(), op));
+ }
+ }
+ _readyHandlers.clear();
+ }
+}
+
+void
+Selector::processInterrupt()
+{
+ Lock sync(*this);
+ if(!_changes.empty())
+ {
+ for(set<EventHandlerWrapperPtr>::const_iterator p = _changes.begin(); p != _changes.end(); ++p)
+ {
+ (*p)->updateRunLoop();
+ }
+ _changes.clear();
+ notify();
+ }
+ if(_destroyed)
+ {
+ CFRunLoopStop(_runLoop);
+ }
+}
+
+void
+Selector::ready(EventHandlerWrapper* wrapper, SocketOperation op, int error)
+{
+ Lock sync(*this);
+ wrapper->ready(op, error);
+}
+
+void
+Selector::addReadyHandler(EventHandlerWrapper* wrapper)
+{
+ // Called from ready()
+ _readyHandlers.push_back(wrapper);
+ if(_readyHandlers.size() == 1)
+ {
+ notify();
+ }
+}
+
+void
+Selector::run()
+{
+ {
+ Lock sync(*this);
+ _runLoop = CFRunLoopGetCurrent();
+ notify();
+ }
+
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), _source, kCFRunLoopDefaultMode);
+ CFRunLoopRun();
+ CFRunLoopRemoveSource(CFRunLoopGetCurrent(), _source, kCFRunLoopDefaultMode);
+}
+
#elif defined(ICE_USE_SELECT) || defined(ICE_USE_POLL)
Selector::Selector(const InstancePtr& instance) : _instance(instance), _selecting(false), _interrupted(false)
diff --git a/cpp/src/Ice/Selector.h b/cpp/src/Ice/Selector.h
index 2e70648bb68..7ca36dee887 100644
--- a/cpp/src/Ice/Selector.h
+++ b/cpp/src/Ice/Selector.h
@@ -28,6 +28,21 @@
# include <sys/poll.h>
#endif
+#if defined(ICE_USE_CFSTREAM)
+# include <IceUtil/RecMutex.h>
+# include <IceUtil/Thread.h>
+# include <set>
+
+struct __CFRunLoop;
+typedef struct __CFRunLoop * CFRunLoopRef;
+
+struct __CFRunLoopSource;
+typedef struct __CFRunLoopSource * CFRunLoopSourceRef;
+
+struct __CFSocket;
+typedef struct __CFSocket * CFSocketRef;
+#endif
+
#if defined(ICE_OS_WINRT)
# include <deque>
#endif
@@ -161,6 +176,120 @@ private:
int _queueFd;
};
+#elif defined(ICE_USE_CFSTREAM)
+
+class Selector;
+
+class SelectorReadyCallback : public IceUtil::Shared
+{
+public:
+
+ virtual ~SelectorReadyCallback() { }
+ virtual void readyCallback(SocketOperation, int = 0) = 0;
+};
+
+class StreamNativeInfo : public NativeInfo
+{
+public:
+
+ StreamNativeInfo(SOCKET fd) : NativeInfo(fd), _connectError(0)
+ {
+ }
+
+ virtual void initStreams(SelectorReadyCallback*) = 0;
+ virtual SocketOperation registerWithRunLoop(SocketOperation) = 0;
+ virtual SocketOperation unregisterFromRunLoop(SocketOperation, bool) = 0;
+ virtual void closeStreams() = 0;
+
+ void setConnectError(int error)
+ {
+ _connectError = error;
+ }
+
+private:
+
+ int _connectError;
+};
+typedef IceUtil::Handle<StreamNativeInfo> StreamNativeInfoPtr;
+
+class EventHandlerWrapper : public SelectorReadyCallback
+{
+public:
+
+ EventHandlerWrapper(const EventHandlerPtr&, Selector&);
+ ~EventHandlerWrapper();
+
+ void updateRunLoop();
+
+ virtual void readyCallback(SocketOperation, int = 0);
+
+ void ready(SocketOperation, int);
+
+ SocketOperation readyOp();
+ void checkReady();
+
+ bool update(SocketOperation, SocketOperation);
+ void finish();
+
+ bool operator<(const EventHandlerWrapper& o)
+ {
+ return this < &o;
+ }
+
+private:
+
+ friend class Selector;
+
+ EventHandlerPtr _handler;
+ StreamNativeInfoPtr _nativeInfo;
+ Selector& _selector;
+ SocketOperation _ready;
+ bool _finish;
+ CFSocketRef _socket;
+ CFRunLoopSourceRef _source;
+};
+typedef IceUtil::Handle<EventHandlerWrapper> EventHandlerWrapperPtr;
+
+class Selector : IceUtil::Monitor<IceUtil::RecMutex>
+{
+
+public:
+
+ Selector(const InstancePtr&);
+ virtual ~Selector();
+
+ void destroy();
+
+ void initialize(EventHandler*);
+ void update(EventHandler*, SocketOperation, SocketOperation);
+ void enable(EventHandler*, SocketOperation);
+ void disable(EventHandler*, SocketOperation);
+ bool finish(EventHandler*, bool);
+
+ void startSelect() { }
+ void finishSelect() { }
+ void select(std::vector<std::pair<EventHandler*, SocketOperation> >&, int);
+
+ void processInterrupt();
+ void ready(EventHandlerWrapper*, SocketOperation, int = 0);
+ void addReadyHandler(EventHandlerWrapper*);
+ void run();
+
+private:
+
+ InstancePtr _instance;
+ IceUtil::ThreadPtr _thread;
+ CFRunLoopRef _runLoop;
+ CFRunLoopSourceRef _source;
+ bool _destroyed;
+
+ std::set<EventHandlerWrapperPtr> _changes;
+
+ std::vector<EventHandlerWrapperPtr> _readyHandlers;
+ std::vector<std::pair<EventHandlerWrapperPtr, SocketOperation> > _selectedHandlers;
+ std::map<EventHandler*, EventHandlerWrapperPtr> _wrappers;
+};
+
#elif defined(ICE_USE_SELECT) || defined(ICE_USE_POLL)
class Selector
diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp
index 02f1eb94d77..eb030600d1e 100644
--- a/cpp/src/slice2cpp/Gen.cpp
+++ b/cpp/src/slice2cpp/Gen.cpp
@@ -8,7 +8,7 @@
// **********************************************************************
#include <IceUtil/DisableWarnings.h>
-#include <Gen.h>
+#include "Gen.h"
#include <Slice/Util.h>
#include <Slice/CPlusPlusUtil.h>
#include <IceUtil/Functional.h>
diff --git a/cpp/src/slice2cpp/Main.cpp b/cpp/src/slice2cpp/Main.cpp
index 98b0b14d07b..5fa6d6d247d 100644
--- a/cpp/src/slice2cpp/Main.cpp
+++ b/cpp/src/slice2cpp/Main.cpp
@@ -14,7 +14,7 @@
#include <Slice/Preprocessor.h>
#include <Slice/FileTracker.h>
#include <Slice/Util.h>
-#include <Gen.h>
+#include "Gen.h"
using namespace std;
using namespace Slice;
diff --git a/cpp/src/slice2objc/Gen.cpp b/cpp/src/slice2objc/Gen.cpp
index 35a8cba1996..a8c6b825ae5 100644
--- a/cpp/src/slice2objc/Gen.cpp
+++ b/cpp/src/slice2objc/Gen.cpp
@@ -9,7 +9,7 @@
#include <IceUtil/DisableWarnings.h>
#include <IceUtil/Functional.h>
-#include <Gen.h>
+#include "Gen.h"
#include <limits>
#include <sys/stat.h>
#ifndef _WIN32
diff --git a/cpp/src/slice2objc/Main.cpp b/cpp/src/slice2objc/Main.cpp
index 91843743c3d..fe9189514a1 100644
--- a/cpp/src/slice2objc/Main.cpp
+++ b/cpp/src/slice2objc/Main.cpp
@@ -14,7 +14,7 @@
#include <IceUtil/Mutex.h>
#include <IceUtil/MutexPtrLock.h>
#include <Slice/Util.h>
-#include <Gen.h>
+#include "Gen.h"
using namespace std;
using namespace Slice;