]> gitweb.hamatoma.de Git - cpidjinn/commitdiff
Timer works without memory leaks
authorhama <hama@siduction.net>
Wed, 8 Jun 2016 22:20:16 +0000 (00:20 +0200)
committerhama <hama@siduction.net>
Wed, 8 Jun 2016 22:20:16 +0000 (00:20 +0200)
.gitignore
Server/Makefile
Server/cpidjinn.hpp
Server/gpiotimer.cpp [new file with mode: 0644]
Server/gpiotimer.hpp [new file with mode: 0644]
util/thread.cpp
util/thread.hpp
util/timer.cpp
util/timer.hpp

index 874c63cfa699b0cb28ada8b48e0f107ee5716f85..8fab6219f3c4329e6e5df15cbb4964e6925f161d 100644 (file)
@@ -1,2 +1,14 @@
 *.o
+Server/cpidjinn
+Server/client
+*.kdev4
+util/test
+src/
+*.gdb
+cl
+cl.gdb
+sv
+sv.gdb
+sv.sh
+util/test.wav
 
index c07910bdb7e1af73473879902659c7a7b5afa8bc..7593f790fd65000836f31e8d76b71114e4b67789 100644 (file)
@@ -4,7 +4,7 @@ CFLAGS = -Wall
 LDFLAGS = -lbcm2835 -lpthread
 
 OBJ_UTIL = timer.o thread.o dynbuffer.o logger.o
-OBJ = cpidjinn.o $(OBJ_UTIL) tcpserver.o gpioprocessor.o
+OBJ = gpiotimer.o cpidjinn.o $(OBJ_UTIL) tcpserver.o gpioprocessor.o
 PROG = cpidjinn
 
 OBJ_CLIENT = $(OBJ_UTIL) tcpclient.o client.o
index 49cb5c1452c2c06dc783e8595cbe1ea8050f1b2f..c4cd173aa3e39634c3b38c6ff6831f64185292b8 100644 (file)
@@ -2,4 +2,5 @@
 #include "util.hpp"
 #include "tcpserver.hpp"
 #include "gpioprocessor.hpp"
+#include "gpiotimer.hpp"
 #endif
diff --git a/Server/gpiotimer.cpp b/Server/gpiotimer.cpp
new file mode 100644 (file)
index 0000000..50c9847
--- /dev/null
@@ -0,0 +1,58 @@
+#include "cpidjinn.hpp"
+
+/**
+ * Constructor.
+ *
+ * @param pin          the pin where the data will be transferred
+ * @param pause                pause in microseconds befor starting the first hight state
+ * @param logger       the logger
+ */
+GPIOTimer::GPIOTimer(int pin, uint64_t pause, Announcer* logger) :
+       Timer(1, 0, pause, uMicroSeconds, true, logger),
+       m_pin(pin)
+{
+}
+
+/**
+ * Destructor.
+ */
+GPIOTimer::~GPIOTimer() {
+
+}
+
+/**
+ * Switches the state of a pin.
+ *
+ * @param high         <i>true</i>: the state will be set to high
+ */
+void GPIOTimer::switchState(bool high){
+       m_logger->sayf(LOG_DEBUG, "%d: %c", m_pin, high ? 'H' : 'L');
+}
+/**
+ * Constructor.
+ *
+ * @param pin          the target pin
+ * @param pause                the pause (in microseconds) to wait before starting the wave
+ * @param count                the number of high states to create
+ * @param high         the duration of the high state in microseconds
+ * @param low          the duration of the low state in microseconds
+ */
+SquareWaveTimer::SquareWaveTimer(int pin, uint64_t pause, int count,
+                                                                uint64_t high, uint64_t low, Announcer* logger) :
+       GPIOTimer(pin, pause, logger),
+       m_pause(pause),
+       m_high(high),
+       m_low(low),
+       m_nextHigh(false){
+       // high + low = factor 2:
+       m_count = count * 2;
+}
+
+/**
+ * The action done from the timer.
+ */
+void SquareWaveTimer::timerTask(){
+       m_nextHigh = ! m_nextHigh;
+       switchState(m_nextHigh);
+       m_delay = m_nextHigh ? m_high : m_low;
+}
diff --git a/Server/gpiotimer.hpp b/Server/gpiotimer.hpp
new file mode 100644 (file)
index 0000000..4205419
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef GPIOTIMER_H
+#define GPIOTIMER_H
+
+/**
+ * Abstract base class for controlling "General input output" pins.
+ */
+class GPIOTimer : public Timer {
+public:
+    GPIOTimer(int pin, uint64_t pause, Announcer* logger);
+    virtual ~GPIOTimer();
+private:
+       // not implemented, private to avoid usage
+    GPIOTimer ( const GPIOTimer& other );
+    GPIOTimer& operator= ( const GPIOTimer& other );
+protected:
+       void switchState(bool high);
+protected:
+       int m_pin;
+};
+
+/**
+ * A timer producing a square wave with constant frequency.
+ */
+class SquareWaveTimer : public GPIOTimer{
+public:
+       SquareWaveTimer(int pin, uint64_t pause, int count,
+                                                                uint64_t high, uint64_t low, Announcer* logger);
+public:
+       virtual void timerTask();
+private:
+       int m_count;
+       uint64_t m_pause;
+       uint64_t m_high;
+       uint64_t m_low;
+       bool m_nextHigh;
+};
+
+/**
+ * A timer producing a melody.
+ *
+ * A melody is a squence of square waves with different frequencies.
+ */
+class MelodyTimer : public GPIOTimer{
+public:
+       MelodyTimer(int pin, DynBuffer& melody);
+public:
+       virtual void timerTask();
+};
+
+#endif // GPIOTIMER_H
index 41ac1e6f4e90bbc10ab0360439f9488a5554a8cb..dc0beb9a1d135e2dc547fad27afc971c77ecdd6a 100644 (file)
@@ -5,15 +5,13 @@
 int ThreadPool::m_currentMaxThreads = 128;
 ThreadPool* ThreadPool::m_instance = NULL;
 const pthread_mutex_t ThreadPool::m_mutexInitializer = PTHREAD_MUTEX_INITIALIZER;
-
-int gv_rounds = 0;
-int gv_calls;
+pthread_mutex_t Thread::m_mutexStarter = PTHREAD_MUTEX_INITIALIZER;
 
 /**
  * Connects the posix thread to the class instance.
  */
 void* threadStarter(void *param){
-       trace("threadstarter");
+       trace1("threadstarter(%llx)", (uint64_t) param);
        Thread* thread = reinterpret_cast<Thread*>(param);
        thread->execute();
        return param;
@@ -53,10 +51,12 @@ void Thread::execute(){
        m_running = true;
        run();
        m_pool.remove(*this);
+       pthread_t pthread = m_pthread;
        if (m_autoDelete){
                trace1("Thread::execute(%d) autodelete\n", m_threadId);
                delete this;
        }
+       pthread_detach(pthread);
 }
 
 /**
@@ -75,8 +75,10 @@ void Thread::microSleep(uint64_t microseconds){
  * Lets the thread run.
  */
 void Thread::start(){
-       pthread_create(&m_pthread, NULL, &threadStarter, this);
+       pthread_attr_t attr;
+       pthread_attr_init(&attr);
        trace2("Thread::start(%d): %lx\n", m_threadId, m_pthread);
+       pthread_create(&m_pthread, &attr, &threadStarter, this);
 }
 /**
  * Introduces the termination of the thread.
@@ -166,27 +168,14 @@ void* ThreadPool::join(int threadId){
        trace1("ThreadPool::join(%d):\n", threadId);
        void* rc = NULL;
        Thread* thread = NULL;
-       pthread_t pthread = -1;
-       bool running = false;
        do {
                lock();
                thread = findById(threadId);
-               if(thread == NULL){
-                       unlock();
-                       break;
-               } else {
-                       pthread = thread->m_pthread;
-                       running = thread->m_running;
-               }
                unlock();
-               if (! running)
+               if (thread != NULL)
                        Thread::microSleep(10*1000);
-       } while(! running);
-       trace2("join: thread: %c %lx\n", thread != NULL ? 't' : 'f', pthread);
-       // Does the thread already exist?
-       if (pthread != (pthread_t) -1)
-               pthread_join(pthread, &rc);
-       trace1("join: rc: %c\n", rc == NULL ? 't' : 'f');
+       } while(thread != NULL);
+       trace2("join: thread: %c %llx\n", thread != NULL ? 't' : 'f', (uint64_t) thread);
        return rc;
 }
 
index 484b9d351251a16c7761a675a773a7ccda13d8b5..6840c40788d7fe7ac2281f908afef6df091b5060 100644 (file)
@@ -28,6 +28,8 @@ public:
 private:
        friend void* threadStarter(void *);
        void execute();
+private:
+       static pthread_mutex_t m_mutexStarter;
 protected:
        int m_threadId;
        bool m_shouldStop;
index 92fff6496df1f64ca7a71992f980090d5ff102a4..13a0a93affba6d42331b699219d6333c3fb2666d 100644 (file)
@@ -16,7 +16,7 @@
 Timer::Timer(int count, int delay, int m_startDelay, Unit unit,
                  bool autoDelete, Announcer* logger, ThreadPool* pool) :
        Thread(logger, autoDelete, pool),
-       m_count(count),
+       m_taskCount(count),
        m_delay(delay),
        m_startDelay(delay),
        m_unit(unit)
@@ -33,35 +33,41 @@ Timer::~Timer() {
  */
 void Timer::run(){
        trace1("Timer::run(%d)\n", threadId());
-       if (m_startDelay > 0){
-               switch (m_unit){
-               case uSeconds:
-                       sleep(m_startDelay);
-                       break;
-               case uMilliSeconds:
-                       microSleep(m_startDelay * 1000);
-                       break;
-               case uMicroSeconds:
-               default:
-                       microSleep(m_startDelay);
-                       break;
-               }
+       if (! m_shouldStop && m_startDelay > 0){
+               sleep(m_startDelay);
        }
-       while(m_count-- > 0){
+       while(! m_shouldStop && m_taskCount-- > 0){
                trace2("Timer::run(%d): %d\n", threadId(), m_count);
                timerTask();
-               switch (m_unit){
-               case Timer::uSeconds:
-                       sleep(m_delay);
-                       break;
-               case Timer::uMilliSeconds:
-                       microSleep(m_delay * 1000);
-                       break;
-               case Timer::uMicroSeconds:
-                       usleep(m_delay);
-                       break;
-               default:
-                       break;
-               }
+               sleep(m_delay);
        }
 }
+
+/**
+ * Sleeps a given amount of microseconds.
+ *
+ * The sleep is broken if a stop request is done.
+ *
+ * @param units                time to wait in units given by <i>m_unit</i>
+ */
+void Timer::sleep(int units){
+       uint64_t microseconds;
+       switch (m_unit){
+       case uSeconds:
+               microseconds = units * (uint64_t) 1000000;
+               break;
+       case uMilliSeconds:
+               microseconds = units * (uint64_t) 1000;
+               break;
+       case uMicroSeconds:
+       default:
+               microseconds = units;
+               break;
+       }
+       while(! m_shouldStop && microseconds >= (uint64_t) 2000000){
+               sleep(1);
+               microseconds -= 1000000;
+       }
+       if (! m_shouldStop)
+               Thread::microSleep(microseconds);
+}
index 95e1da2002dc312e4d49805c5b929e3dfebf9315..3d34d41e91708494d95263f687f46aff6552165e 100644 (file)
@@ -25,8 +25,9 @@ public:
        virtual void timerTask() = 0;
 private:
        virtual void run();
-private:
-       int m_count;
+       void sleep(int units);
+protected:
+       int m_taskCount;
        int m_delay;
        int m_startDelay;
        Unit m_unit;