Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Besturingssystemen: opdracht 1
- Academiejaar 2016-2017
- Naam: ...
- */
- /*
- Lees aandachtig de commentaar in de code!
- Je mag overal waar je dat nodig acht code aanvullen,
- dus niet enkel op de plaatsen waar commentaar staat.
- */
- #include <iostream>
- #include <fstream>
- #include <pthread.h>
- #include <stdlib.h>
- #ifdef WIN32
- # include <process.h>
- #else
- # include <time.h>
- #endif
- static void Error(const char *str)
- {
- std::cerr << str << std::endl;
- exit(0);
- }
- class Data
- {
- public:
- Data() : refcount(0), value(0) {}
- void ref() { refcount++; }
- void unref() { refcount--; }
- bool isUnused(){ return ( refcount == 0 ); }
- void setValue(int val){ value = val; }
- void print(std::ostream &ostr) { ostr << value << std::endl; }
- private:
- unsigned int refcount;
- int value;
- };
- class Buffer
- {
- public:
- Buffer() : lastProduced(0) {}
- public:
- Data *getEmptyDataElement()
- {
- Data *d = 0; /* = empty data element */;
- for (int i=0; i<BUFFERSIZE; i++)
- {
- if (/* element is free */) {
- d = &storage[i];
- break;
- }
- }
- return d;
- }
- Data *getLastProducedData(Data* previous)
- {
- // check if new element is available
- Data *d = lastProduced;
- d->ref();
- return d;
- }
- void publish(Data *d) /* update last produced, so getLastProducedData returns the correct element */
- {
- lastProduced = d;
- }
- void release(Data *d) /* update handled element, to make it available via getEmptyDataElement */
- {
- d->unref();
- }
- private:
- static const int BUFFERSIZE = 10;
- Data storage[BUFFERSIZE];
- Data *lastProduced;
- };
- static void *start_thread(void *t);
- class Thread
- {
- public:
- Thread() : tid(0) {}
- void start()
- {
- if( pthread_create(&tid, 0, start_thread, (void *) this) != 0 )
- Error("Error: failed to create thread");
- }
- void wait()
- {
- void *status;
- pthread_join(tid, &status);
- }
- static void sleep(unsigned int msecs)
- {
- #ifdef WIN32
- if( SleepEx(msecs, TRUE) != 0 )
- Error("Error: SleepEx interrupted");
- #else
- struct timespec timeout; // timeout value for wait function
- // prepare timeout value
- timeout.tv_sec = msecs / 1000;
- msecs -= timeout.tv_sec * 1000;
- timeout.tv_nsec = (1000 * msecs) * 1000;
- if( nanosleep(&timeout, 0) != 0 )
- Error("Error: nanosleep interrupted or failed");
- #endif
- }
- virtual void run() = 0;
- private:
- pthread_t tid;
- };
- static void *start_thread(void *t)
- {
- reinterpret_cast<Thread *>(t)->run();
- return 0;
- }
- class Producer : public Thread
- {
- public:
- Producer(Buffer &b, long sequenceNumber) : buffer(b), sequenceNumber(sequenceNumber) {}
- private:
- void run()
- {
- for(int i = 0; i < 1000; ++i)
- {
- Data *d = buffer.getEmptyDataElement();
- produceData(d);
- buffer.publish(d);
- }
- }
- void produceData(Data *d)
- {
- Thread::sleep((float(rand()) / RAND_MAX) * 1000); // sleep between 0 and 1 sec
- d->setValue(sequenceNumber++);
- d->print(std::cout);
- }
- Buffer &buffer;
- long sequenceNumber;
- };
- class Handler : public Thread
- {
- public:
- Handler(Buffer &b, std::ostream &ostr) : buffer(b), ostr(ostr) {}
- private:
- void run()
- {
- Data *previous = 0;
- while( /* data available or producer active */ )
- {
- Data *d = buffer.getLastProducedData(previous);
- handleData(d);
- buffer.release(d);
- previous = d;
- }
- }
- void handleData(Data *d)
- {
- d->print(ostr);
- Thread::sleep((float(rand()) / RAND_MAX) * 1000); // sleep between 0 and 1 sec
- }
- Buffer &buffer;
- std::ostream &ostr;
- };
- int main()
- {
- Buffer buff;
- std::ofstream file1;
- std::ofstream file2;
- // open the files
- Producer p(buff, 0);
- Handler h1(buff, std::cout), h2(buff, file1), h3(buff, file2);
- p.start();
- h1.start();
- h2.start();
- h3.start();
- // wait until producers stopped producing and handlers handled all produced data
- return EXIT_SUCCESS;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement