CORBA-omniORB

 view release on metacpan or  search on metacpan

pomni.h  view on Meta::CPAN

#define CM_DEBUG(v)	cm_log v
#endif

//-------------------------------------------------------------------

// C++-friendly croak()

// Trampoline classes

class POmniCroak {
public:
    POmniCroak(pTHX_ const char *fmt, ...) {
	va_list ap;
	va_start(ap, fmt);

	SV *errsv = get_sv("@", TRUE);
	sv_vsetpvf(errsv, fmt, &ap);

	va_end(ap);
    }
};

class POmniThrowable {
    SV *e_;
public:
    POmniThrowable(SV *e)
	: e_(e) {
    }

    SV *exception_object(void) {
	return e_;
    }
};

#define CATCH_POMNI_TRAMPOLINE \
    catch (POmniCroak) { \
	croak(Nullch); \
    } \
    catch (POmniThrowable &throwable) { \
	pomni_throw(aTHX_ throwable.exception_object()); \
    }

#define CATCH_POMNI_SYSTEMEXCEPTION \
    catch (CORBA::SystemException &sysex) { \
        pomni_throw(aTHX_ pomni_system_except(aTHX_ \
                                              sysex._rep_id(), \
                                              sysex.minor(), \
                                              sysex.completed())); \
    }


//-------------------------------------------------------------------

/** Mutex to serialize servant calls from omniORB.  Allows the mutex
 * to be temporarily released to allow callbacks with a deeper
 * recursion level to execute.
 */

class POmniRatchetLock {
    omni_mutex mutex_;
    volatile bool locked_;
    omni_condition entry_cond_;
    volatile unsigned awaiting_entry_;

    struct Entry {
	bool waiting;
	omni_condition *cond;
	Entry(omni_mutex *mutex)
	    : waiting(false), cond(new omni_condition(mutex)) {
	}
    };

    typedef std::vector<Entry> _T;
    _T stack_;
    _T::iterator top_;		// Stack top
    
    inline void grow() {
	_T::size_type top = top_ - stack_.begin();
	stack_.push_back(Entry(&mutex_)); // Invalidates iterators
	top_ = stack_.begin() + top;
    }
    
public:
    POmniRatchetLock(void)
	: locked_(true),
	  entry_cond_(&mutex_),
	  awaiting_entry_(0),
	  top_(stack_.begin()) {
	grow();			// initial entry
    }
    ~POmniRatchetLock(void) {
	for(_T::iterator i = stack_.begin(); i != stack_.end(); ++i) {
	    delete i->cond;
	}
    }

    //! Enter a new recursion level.
    void enter(void) {
	mutex_.lock();
	++awaiting_entry_;
	while(locked_)
	    entry_cond_.wait();
	--awaiting_entry_;
	++top_;
	if(top_ == stack_.end())
	    grow();
	locked_ = true;
	mutex_.unlock();
    }

    //! Exit the current recursion level.
    void leave(void) {
	mutex_.lock();
	locked_ = false;
	--top_;
	if(awaiting_entry_ > 0)
	    entry_cond_.signal();
	else if(top_->waiting)
	    top_->cond->signal();
	mutex_.unlock();
    }

    //! Token used to indicate the current recursion level for later
    // resumption.
    typedef _T::size_type token;

    //! Release the lock for use by deeper recursion levels.
    token release(void) {
	mutex_.lock();
	locked_ = false;
	if(awaiting_entry_ > 0)
	    entry_cond_.signal();
	token t = top_ - stack_.begin();
	mutex_.unlock();
	return t;
    }

    //! Resume the specified recursion level.
    void resume(token t) {
	mutex_.lock();
	_T::iterator ti = stack_.begin() + t;
	ti->waiting = true;
	while(locked_ || ti != top_) {
	    ti->cond->wait();
	    ti = stack_.begin() + t;
	}
	ti->waiting = false;
	locked_ = true;
	mutex_.unlock();
    }
};

// Return the entry lock for the current Perl interpreter
POmniRatchetLock *pomni_entry_lock(pTHX);

/** Object to temporarily unlock the Perl interpreter during a blocking
 * operation, allowing other threads to make use of the interpreter.
 * Usage should follow the pattern:
 *
 *  PUTBACK;
 *  {
 *      POmniPerlEntryUnlocker ul(aTHX);
 *      <some potentially blocking operation>
 *  }
 *  SPAGAIN;
 */
class POmniPerlEntryUnlocker {
    POmniRatchetLock *entry_lock_;
    POmniRatchetLock::token t_;
public:
    POmniPerlEntryUnlocker(pTHX)
	: entry_lock_(pomni_entry_lock(aTHX)),
	  t_(entry_lock_ ? entry_lock_->release() : 0) {
    }
    ~POmniPerlEntryUnlocker(void) {
	if (entry_lock_)
	    entry_lock_->resume(t_);
    }
};

/*!
 * ORB instance
 */
extern CORBA::ORB_ptr pomni_orb;



( run in 1.280 second using v1.01-cache-2.11-cpan-5c0b1e786e0 )