summaryrefslogtreecommitdiff
path: root/cpp/src/IceGrid/Allocatable.cpp
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2006-04-25 14:46:33 +0000
committerBenoit Foucher <benoit@zeroc.com>2006-04-25 14:46:33 +0000
commit9f1ce09c6c0ae5dbf7313e6bff08bbf8a6974db9 (patch)
tree2f6dd493e5b2c2ec24a59fd244912fc59f3e2d8d /cpp/src/IceGrid/Allocatable.cpp
parentadding some comments with respect to changes to proxyToString() possibly (diff)
downloadice-9f1ce09c6c0ae5dbf7313e6bff08bbf8a6974db9.tar.bz2
ice-9f1ce09c6c0ae5dbf7313e6bff08bbf8a6974db9.tar.xz
ice-9f1ce09c6c0ae5dbf7313e6bff08bbf8a6974db9.zip
More work on object allocation.
Diffstat (limited to 'cpp/src/IceGrid/Allocatable.cpp')
-rw-r--r--cpp/src/IceGrid/Allocatable.cpp172
1 files changed, 120 insertions, 52 deletions
diff --git a/cpp/src/IceGrid/Allocatable.cpp b/cpp/src/IceGrid/Allocatable.cpp
index 4760bafe09b..510663cf9ca 100644
--- a/cpp/src/IceGrid/Allocatable.cpp
+++ b/cpp/src/IceGrid/Allocatable.cpp
@@ -20,13 +20,28 @@ AllocationRequest::~AllocationRequest()
bool
AllocationRequest::setAllocatable(const AllocatablePtr& allocatable)
{
+ assert(allocatable);
+
Lock sync(*this);
- assert(!_allocatable);
- if(_canceled)
+ switch(_state)
{
+ case Initial:
+ break;
+ case Canceled:
return false;
+ case Pending:
+ if(_timeout > 0)
+ {
+ _session->getWaitQueue()->remove(this);
+ }
+ break;
+ case Allocated:
+ assert(false);
+ break;
}
+
_allocatable = allocatable;
+ _state = Allocated;
allocated(_allocatable);
return true;
}
@@ -34,53 +49,83 @@ AllocationRequest::setAllocatable(const AllocatablePtr& allocatable)
void
AllocationRequest::cancel()
{
- Lock sync(*this);
- if(_canceled)
+ AllocatablePtr allocatable;
{
- return;
+ Lock sync(*this);
+ switch(_state)
+ {
+ case Initial:
+ assert(false);
+ case Canceled:
+ return;
+ case Pending:
+ if(_timeout > 0)
+ {
+ _session->getWaitQueue()->remove(this);
+ }
+ canceled();
+ break;
+ case Allocated:
+ allocatable = _allocatable;
+ break;
+ }
+
+ _state = Canceled;
}
- _canceled = true;
- canceled();
-}
-bool
-AllocationRequest::checkTimeout(const IceUtil::Time& now)
-{
- assert(_timeout > 0);
+ if(allocatable)
{
- Lock sync(*this);
- if(_canceled)
+ try
{
- return true;
+ allocatable->release(_session);
}
- _canceled = _expiration < now;
- if(!_canceled)
+ catch(const AllocationException&)
{
- return false;
+ // Ignore, the allocatable might already have been released.
}
+ }
+}
+
+void
+AllocationRequest::expired(bool destroyed)
+{
+ Lock sync(*this);
+ switch(_state)
+ {
+ case Initial:
+ assert(false);
+ case Canceled:
+ return;
+ case Pending:
timeout();
+ break;
+ case Allocated:
+ return;
}
- _session->removeAllocationRequest(this);
- return true;
+
+ _state = Canceled;
}
void
AllocationRequest::allocate()
{
_session->addAllocationRequest(this);
+
+ Lock sync(*this);
+ assert(_allocatable || _state == Initial);
+ if(!_allocatable)
+ {
+ if(_timeout > 0)
+ {
+ _session->getWaitQueue()->add(this, IceUtil::Time::milliSeconds(_timeout));
+ }
+ _state = Pending;
+ }
}
void
-AllocationRequest::release(const SessionIPtr& session)
+AllocationRequest::release()
{
- //
- // Check if the session releasing the object is indeed the session
- // which initiated the allocation request.
- //
- if(_session != session)
- {
- throw AllocationException("can't release object which is not allocated");
- }
_session->removeAllocationRequest(this);
}
@@ -92,9 +137,8 @@ AllocationRequest::operator<(const AllocationRequest& r) const
AllocationRequest::AllocationRequest(const SessionIPtr& session) :
_session(session),
- _timeout(_session->getAllocationTimeout()),
- _expiration(_timeout > 0 ? (IceUtil::Time::now() + IceUtil::Time::milliSeconds(_timeout)) : IceUtil::Time()),
- _canceled(false)
+ _timeout(_session->getAllocationTimeout()), // The session timeout can be updated so we need to cache it here.
+ _state(Initial)
{
}
@@ -107,7 +151,7 @@ Allocatable::~Allocatable()
}
void
-Allocatable::allocate(const AllocationRequestPtr& request, bool allocateOnce)
+Allocatable::allocate(const AllocationRequestPtr& request, bool once)
{
IceUtil::Mutex::Lock sync(_allocateMutex);
if(_allocatable)
@@ -116,11 +160,14 @@ Allocatable::allocate(const AllocationRequestPtr& request, bool allocateOnce)
{
if(_allocated->getSession() == request->getSession())
{
- if(allocateOnce)
+ if(once)
{
throw AllocationException("object already allocated by the session");
}
- request->setAllocatable(this);
+ else
+ {
+ request->setAllocatable(this);
+ }
}
else if(request->getTimeout())
{
@@ -136,16 +183,12 @@ Allocatable::allocate(const AllocationRequestPtr& request, bool allocateOnce)
{
_allocated = request;
_allocated->allocate();
+ allocated();
}
}
else
{
- if(allocateOnce)
- {
- throw AllocationException("can't allocate non allocatable object");
- }
- bool rc = request->setAllocatable(this);
- assert(rc);
+ throw AllocationException("can't allocate non allocatable object");
}
}
@@ -153,35 +196,60 @@ bool
Allocatable::tryAllocate(const AllocationRequestPtr& request)
{
IceUtil::Mutex::Lock sync(_allocateMutex);
- if(_allocatable && _allocated)
+ if(_allocatable)
{
- return false;
+ if(_allocated)
+ {
+ if(_allocated->getSession() == request->getSession())
+ {
+ throw AllocationException("object already allocated by the session");
+ }
+ return false;
+ }
+ else if(request->setAllocatable(this))
+ {
+ _allocated = request;
+ _allocated->allocate();
+ allocated();
+ }
+ return true; // The allocatable was allocated or the request was canceled.
}
- else if(request->setAllocatable(this))
+ else
{
- _allocated = request;
- _allocated->allocate();
+ return false;
}
- return true;
}
-void
+bool
Allocatable::release(const SessionIPtr& session)
{
IceUtil::Mutex::Lock sync(_allocateMutex);
- if(!_allocated)
+ if(!_allocated || _allocated->getSession() != session)
{
- throw AllocationException("object not allocated");
+ throw AllocationException("can't release object which is not allocated");
}
- _allocated->release(session);
+ _allocated->release();
+
+ //
+ // Allocate the allocatable to another client.
+ //
while(!_requests.empty())
{
_allocated = _requests.front();
_requests.pop_front();
if(_allocated->setAllocatable(this))
{
- return;
+ return false;
}
}
+ released();
_allocated = 0;
+ return true;
+}
+
+bool
+Allocatable::isAllocated() const
+{
+ IceUtil::Mutex::Lock sync(_allocateMutex);
+ return _allocated;
}