Commit b781545c authored by Georg Kunz's avatar Georg Kunz

[master] streamlined templated implementation of locks

parent a787bc0a
//==========================================================================
// CLOCK.H - part of
//
// Horizon/OMNeT++/OMNEST
// Discrete System Simulation in C++
//
//
// Declaration of the following classes:
// cLock: Baseclass for different implementations of threadsafe locks.
//
//==========================================================================
/*--------------------------------------------------------------*
Copyright (C) 2011 Simon Tenbusch
This file is distributed WITHOUT ANY WARRANTY. See the file
`license' for details on this and other legal matters.
*--------------------------------------------------------------*/
#ifndef CLOCK_H_
#define CLOCK_H_
#include "simkerneldefs.h"
class cLock
{
public:
/*
* Locks the lock
*/
virtual void lock() = 0;
/*
* Unlocks the lock
*/
virtual void unlock() = 0;
};
#endif /* CLOCK_H_ */
......@@ -22,9 +22,7 @@
#define __CLOCKEDDEFAULTLIST_H
#include <pthread.h>
#include "cdefaultlist.h"
#include "clock.h"
/**
......@@ -36,8 +34,7 @@ template<class T>
class SIM_API cLockedDefaultList : public cDefaultList
{
private:
cLock* lock; // the lock
T lock;
//void construct();
virtual void doInsert(cOwnedObject *obj); // called from constructor of cObject
......
......@@ -13,6 +13,7 @@
Copyright (C) 1992-2005 Andras Varga
Copyright (C) 2010 Georg Kunz
Copyright (C) 2011 Simon Tenbusch
Copyright (C) 2012 Georg Kunz
This file is distributed WITHOUT ANY WARRANTY. See the file
`license' for details on this and other legal matters.
......@@ -22,7 +23,6 @@
#define __CLOCKEDMSGHEAP_H
#include "cobject.h"
#include "clock.h"
#include "cpthreadlock.h"
class cMessage;
......@@ -38,32 +38,34 @@ template <class T>
class SIM_API cLockedMessageHeap : public cMessageHeap
{
private:
cLock* lock; // the lock
T lock; // the lock
public:
/** @name Constructors, destructor, assignment */
//@{
/**
* Copy constructor.
*/
cLockedMessageHeap(const cLockedMessageHeap& msgq);
/**
* Constructor.
*/
cLockedMessageHeap(const char *name=NULL, int size=128);
cLockedMessageHeap(const char *name=NULL, int size=128) :
cMessageHeap(name, size),
lock()
{
}
/**
* Destructor.
* Copy constructor.
*/
virtual ~cLockedMessageHeap();
cLockedMessageHeap(const cLockedMessageHeap& heap) :
cMessageHeap(heap)
{
}
/**
* Assignment operator. The name member doesn't get copied;
* see cObject's operator=() for more details.
*/
cLockedMessageHeap& operator=(const cLockedMessageHeap& msgqueue);
//cLockedMessageHeap& operator=(const cLockedMessageHeap& msgqueue);
//@}
/** @name Redefined cObject member functions. */
......@@ -73,13 +75,24 @@ class SIM_API cLockedMessageHeap : public cMessageHeap
* Creates and returns an exact copy of this object.
* See cObject for more details.
*/
virtual cObject *dup();
virtual cObject *dup()
{
lock.lock();
cObject* p = cMessageHeap::dup();
lock.unlock();
return p;
}
/**
* Calls v->visit(this) for each contained object.
* See cObject for more details.
*/
virtual void forEachChild(cVisitor *v);
inline void forEachChild(cVisitor *v)
{
lock.lock();
cMessageHeap::forEachChild(v);
lock.unlock();
}
// no netPack() and netUnpack()
//@}
......@@ -90,19 +103,36 @@ class SIM_API cLockedMessageHeap : public cMessageHeap
/**
* Insert a new message into the heap.
*/
void insert(cMessage *event);
inline void insert(cMessage *event)
{
lock.lock();
cMessageHeap::insert(event);
lock.unlock();
}
/**
* Removes and return the first message in the heap (the one
* with the smallest timestamp.) If the heap is empty, it returns NULL.
*/
cMessage *removeFirst();
inline cMessage *removeFirst()
{
lock.lock();
cMessage* msg = cMessageHeap::removeFirst();
lock.unlock();
return msg;
}
/**
* Removes and returns the given message in the heap. If the message is
* not in the heap, returns NULL.
*/
cMessage *remove(cMessage *event);
inline cMessage *remove(cMessage *event)
{
lock.lock();
cMessage* msg = cMessageHeap::remove(event);
lock.unlock();
return msg;
}
/**
* Returns the mth message in the heap if 0 <= m < length(), and NULL
......@@ -110,122 +140,47 @@ class SIM_API cLockedMessageHeap : public cMessageHeap
* in increasing timestamp (arrivalTime()) order unless you called
* sort() before.
*/
cMessage *peek(int m);
inline cMessage *peek(int m)
{
lock.lock();
cMessage* msg = cMessageHeap::peek(m);
lock.unlock();
return msg;
}
/*
* See peek(1)
*/
cMessage *peekFirst();
inline cMessage *peekFirst()
{
lock.lock();
cMessage* msg = cMessageHeap::peekFirst();
lock.unlock();
return msg;
}
/**
* Sorts the contents of the heap. This is only necessary if one wants
* to iterate through in the FES in strict timestamp order.
*/
void sort();
inline void sort()
{
lock.lock();
cMessageHeap::sort();
lock.unlock();
}
/**
* Deletes all messages in the heap.
*/
void clear();
inline void clear()
{
lock.lock();
cMessageHeap::clear();
lock.unlock();
}
//@}
};
template <class T>
cLockedMessageHeap<T>::cLockedMessageHeap(const char *name, int siz) :
cMessageHeap(name, siz)
{
lock = new T();
}
template <class T>
cLockedMessageHeap<T>::cLockedMessageHeap(const cLockedMessageHeap& heap) :
cMessageHeap(heap)
{
lock = new T();
}
template <class T>
cLockedMessageHeap<T>::~cLockedMessageHeap<T>()
{
delete lock;
}
template <class T>
cObject* cLockedMessageHeap<T>::dup()
{
lock->lock();
cObject* p = cMessageHeap::dup();
lock->unlock();
return p;
}
template <class T>
void cLockedMessageHeap<T>::forEachChild(cVisitor *v)
{
lock->lock();
cMessageHeap::forEachChild(v);
lock->unlock();
}
template <class T>
void cLockedMessageHeap<T>::clear()
{
lock->lock();
cMessageHeap::clear();
lock->unlock();
}
template <class T>
cMessage *cLockedMessageHeap<T>::peek(int m)
{
lock->lock();
cMessage* msg = cMessageHeap::peek(m);
lock->unlock();
return msg;
}
template <class T>
cMessage *cLockedMessageHeap<T>::peekFirst()
{
lock->lock();
cMessage* msg = cMessageHeap::peekFirst();
lock->unlock();
return msg;
}
template <class T>
void cLockedMessageHeap<T>::sort()
{
lock->lock();
cMessageHeap::sort();
lock->unlock();
}
template <class T>
void cLockedMessageHeap<T>::insert(cMessage *event)
{
lock->lock();
cMessageHeap::insert(event);
lock->unlock();
}
template <class T>
cMessage *cLockedMessageHeap<T>::removeFirst()
{
lock->lock();
cMessage* msg = cMessageHeap::removeFirst();
lock->unlock();
return msg;
}
template <class T>
cMessage *cLockedMessageHeap<T>::remove(cMessage *event)
{
lock->lock();
cMessage* msg = cMessageHeap::remove(event);
lock->unlock();
return msg;
}
#endif
......@@ -21,7 +21,6 @@
#define __CMESSAGEHEAP_H
#include "cownedobject.h"
#include "clock.h"
NAMESPACE_BEGIN
......@@ -49,8 +48,6 @@ class SIM_API cMessageHeap : public cOwnedObject
cMessageHeap *q;
int pos;
cLock* lock;
public:
/**
* Constructor.
......
......@@ -12,6 +12,7 @@
/*--------------------------------------------------------------*
Copyright (C) 2011 Simon Tenbusch
Copyright (C) 2012 Georg Kunz
This file is distributed WITHOUT ANY WARRANTY. See the file
`license' for details on this and other legal matters.
......@@ -20,34 +21,22 @@
#ifndef CNOLOCK_H_
#define CNOLOCK_H_
#include "clock.h"
class cNoLock: public cLock
class cNoLock
{
private:
public:
/**
* Constructor.
*/
cNoLock();
/**
* Destructor.
*/
virtual ~cNoLock();
/*
* Locks the lock
*/
void lock()
inline void lock()
{
}
/*
* Unlocks the lock
*/
void unlock()
inline void unlock()
{
}
};
......
......@@ -12,6 +12,7 @@
/*--------------------------------------------------------------*
Copyright (C) 2011 Simon Tenbusch
Copyright (C) 2012 Georg Kunz
This file is distributed WITHOUT ANY WARRANTY. See the file
`license' for details on this and other legal matters.
......@@ -20,35 +21,45 @@
#ifndef CPTHREADLOCK_H_
#define CPTHREADLOCK_H_
#include "clock.h"
#include <pthread.h>
class cPThreadLock: public cLock
class cPThreadLock
{
private:
pthread_mutex_t mutex;
public:
/**
* Constructor.
*/
cPThreadLock();
cPThreadLock()
{
pthread_mutex_init(&mutex, NULL);
}
/**
* Destructor.
*/
virtual ~cPThreadLock();
virtual ~cPThreadLock()
{
pthread_mutex_destroy(&mutex);
}
/*
* Locks the lock
*/
virtual void lock();
inline void lock()
{
pthread_mutex_lock(&mutex);
}
/*
* Unlocks the lock
*/
virtual void unlock();
inline void unlock()
{
pthread_mutex_unlock(&mutex);
}
};
#endif /* CPHTREADLOCK_H_ */
......@@ -26,8 +26,9 @@
#include "cexception.h"
#include "clockedmsgheap.h"
#include "clock.h"
#include "cttaslock.h"
#include "cnolock.h"
#include "cpthreadlock.h"
#include "cthreadpool.h"
#include "cstopwatch.h"
......@@ -134,6 +135,11 @@ class SIM_API cSimulation : public cNamedObject, noncopyable
#ifdef UNSAFE_FES
cMessageHeap msgQueue; // future messages (FES)
#else
//
// choose on of the following locks
//
// cLockedMessageHeap<cNoLock> msgQueue;
// cLockedMessageHeap<cPThreadLock> msgQueue;
cLockedMessageHeap<cTTASLock> msgQueue;
#endif
......
......@@ -20,39 +20,58 @@
#ifndef CTTASLOCK_H_
#define CTTASLOCK_H_
#include "clock.h"
#ifdef ATOMIC_OPS_DEBUG
#include "catomicopsdebug.h"
#else
#include <atomic_ops.h>
#endif
class cTTASLock: public cLock
class cTTASLock
{
private:
AO_t lck;
static const AO_t unlocked = 0;
static const AO_t locked = 1;
public:
/**
* Constructor.
*/
cTTASLock();
/**
* Destructor.
*/
virtual ~cTTASLock();
cTTASLock()
{
AO_store_write(&lck, 0);
}
/*
* Locks the lock
*/
void lock();
inline void lock()
{
//
// very simply TTAS based spinlock. Does not scale with the number of CPUs
// and should thus be replaced by more complex locks.
//
while (true)
{
while (AO_load_full(&lck) == locked)
{
__asm__ ("pause");
}
if (AO_compare_and_swap_full(&lck, unlocked, locked) != 0)
{
return;
}
}
}
/*
* Unlocks the lock
*/
void unlock();
inline void unlock()
{
AO_store_full(&lck, unlocked);
}
};
......
......@@ -98,11 +98,11 @@ $O/cmdenv.o: cmdenv.cc \
../../include/cconfigoption.h \
../../include/cproperties.h \
../../include/cregistrationlist.h \
../../include/platdep/timeutil.h \
../../include/cconfiguration.h \
../../include/opp_string.h \
../envir/intervals.h \
../../include/simkerneldefs.h \
../../include/clock.h \
../../include/cthreadpool.h \
../../include/csimulation.h \
../../include/errmsg.h \
......@@ -111,12 +111,14 @@ $O/cmdenv.o: cmdenv.cc \
../../include/cobject.h \
../../include/onstartup.h \
../envir/envirbase.h \
../../include/envirext.h \
../../include/clistener.h \
../../include/envirext.h \
../../include/cdummystringpool.h \
../../include/cstringpool.h \
../../include/cscheduler.h \
../../include/cpar.h \
../../include/globals.h \
../../include/ctaskheap.h \
../envir/appreg.h \
../../include/cdefaultlist.h \
../../include/cvisitor.h \
......@@ -124,6 +126,7 @@ $O/cmdenv.o: cmdenv.cc \
../../include/cttaslock.h \
../../include/csimplemodule.h \
../../include/cobjectfactory.h \
../../include/cnolock.h \
../../include/cmodule.h \
../../include/platdep/platmisc.h \
../../include/cmessageheap.h \
......
This diff is collapsed.
This diff is collapsed.
......@@ -40,9 +40,9 @@ USING_NAMESPACE
template<class T>
cLockedDefaultList<T>::cLockedDefaultList(const char *name) :
cDefaultList(name)
cDefaultList(name),
lock()
{
lock = new T();
}
template<class T>
......
//==========================================================================
// CPTHREADLOCK.CC - part of
//
// Horizon/OMNeT++/OMNEST
// Discrete System Simulation in C++
//
//==========================================================================
/*--------------------------------------------------------------*
Copyright (C) 2011 Simon Tenbusch
This file is distributed WITHOUT ANY WARRANTY. See the file
`license' for details on this and other legal matters.
*--------------------------------------------------------------*/
#include "simkerneldefs.h"
#include "cpthreadlock.h"
cPThreadLock::cPThreadLock()
{
pthread_mutex_init(&mutex, NULL);
}
cPThreadLock::~cPThreadLock()
{
pthread_mutex_destroy(&mutex);
}
void cPThreadLock::lock()
{
pthread_mutex_lock(&mutex);
}
void cPThreadLock::unlock()
{
pthread_mutex_unlock(&mutex);
}
//==========================================================================
// CTTASLOCK.CC - part of
//
// Horizon/OMNeT++/OMNEST
// Discrete System Simulation in C++
//
//==========================================================================
/*--------------------------------------------------------------*
Copyright (C) 2011 Simon Tenbusch
This file is distributed WITHOUT ANY WARRANTY. See the file
`license' for details on this and other legal matters.
*--------------------------------------------------------------*/
#include "simkerneldefs.h"
#include "cttaslock.h"
cTTASLock::cTTASLock()