Robert Sochuliak
/
Vytah
test
Diff: Protothread.h
- Revision:
- 0:e541909ea6b0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Protothread.h Thu Jan 24 06:35:38 2019 +0000 @@ -0,0 +1,160 @@ +// Protothread class and macros for lightweight, stackless threads in C++. +// +// This was "ported" to C++ from Adam Dunkels' protothreads C library at: +// http://www.sics.se/~adam/pt/ +// +// Originally ported for use by Hamilton Jet (www.hamiltonjet.co.nz) by +// Ben Hoyt, but stripped down for public release. See his blog entry about +// it for more information: +// http://blog.brush.co.nz/2008/07/protothreads/ +// +// Visual Studio users: There's a quirk with VS where it defines __LINE__ +// as a non-constant when you've got a project's Debug Information Format +// set to "Program Database for Edit and Continue (/ZI)" -- the default. +// To fix, just go to the project's Properties, Configuration Properties, +// C/C++, General, Debug Information Format, and change it to "Program +// Database (/Zi)". +// +// -------------------------- +// Original BSD-style license +// -------------------------- +// Copyright (c) 2004-2005, Swedish Institute of Computer Science. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the Institute nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// This software is provided by the Institute and contributors "as is" and +// any express or implied warranties, including, but not limited to, the +// implied warranties of merchantability and fitness for a particular purpose +// are disclaimed. In no event shall the Institute or contributors be liable +// for any direct, indirect, incidental, special, exemplary, or consequential +// damages (including, but not limited to, procurement of substitute goods +// or services; loss of use, data, or profits; or business interruption) +// however caused and on any theory of liability, whether in contract, strict +// liability, or tort (including negligence or otherwise) arising in any way +// out of the use of this software, even if advised of the possibility of +// such damage. +// + +#ifndef __PROTOTHREAD_H__ +#define __PROTOTHREAD_H__ + +// A lightweight, stackless thread. Override the Run() method and use +// the PT_* macros to do work of the thread. +// +// A simple example +// ---------------- +// class LEDFlasher : public Protothread +// { +// public: +// virtual bool Run(); +// +// private: +// ExpiryTimer _timer; +// uintf _i; +// }; +// +// bool LEDFlasher::Run() +// { +// PT_BEGIN(); +// +// for (_i = 0; _i < 10; _i++) +// { +// SetLED(true); +// _timer.Start(250); +// PT_WAIT_UNTIL(_timer.Expired()); +// +// SetLED(false); +// _timer.Start(750); +// PT_WAIT_UNTIL(_timer.Expired()); +// } +// +// PT_END(); +// } +// +class Protothread +{ +public: + // Construct a new protothread that will start from the beginning + // of its Run() function. + Protothread() : _ptLine(0) { } + + // Restart protothread. + void Restart() { _ptLine = 0; } + + // Stop the protothread from running. Happens automatically at PT_END. + // Note: this differs from the Dunkels' original protothread behaviour + // (his restart automatically, which is usually not what you want). + void Stop() { _ptLine = LineNumberInvalid; } + + // Return true if the protothread is running or waiting, false if it has + // ended or exited. + bool IsRunning() { return _ptLine != LineNumberInvalid; } + + // Run next part of protothread or return immediately if it's still + // waiting. Return true if protothread is still running, false if it + // has finished. Implement this method in your Protothread subclass. + virtual bool Run() = 0; + +protected: + // Used to store a protothread's position (what Dunkels calls a + // "local continuation"). + typedef unsigned short LineNumber; + + // An invalid line number, used to mark the protothread has ended. + static const LineNumber LineNumberInvalid = (LineNumber)(-1); + + // Stores the protothread's position (by storing the line number of + // the last PT_WAIT, which is then switched on at the next Run). + LineNumber _ptLine; +}; + +// Declare start of protothread (use at start of Run() implementation). +#define PT_BEGIN() bool ptYielded = true; (void) ptYielded; switch (_ptLine) { case 0: + +// Stop protothread and end it (use at end of Run() implementation). +#define PT_END() default: ; } Stop(); return false; + +// Cause protothread to wait until given condition is true. +#define PT_WAIT_UNTIL(condition) \ + do { _ptLine = __LINE__; case __LINE__: \ + if (!(condition)) return true; } while (0) + +// Cause protothread to wait while given condition is true. +#define PT_WAIT_WHILE(condition) PT_WAIT_UNTIL(!(condition)) + +// Cause protothread to wait until given child protothread completes. +#define PT_WAIT_THREAD(child) PT_WAIT_WHILE((child).Run()) + +// Restart and spawn given child protothread and wait until it completes. +#define PT_SPAWN(child) \ + do { (child).Restart(); PT_WAIT_THREAD(child); } while (0) + +// Restart protothread's execution at its PT_BEGIN. +#define PT_RESTART() do { Restart(); return true; } while (0) + +// Stop and exit from protothread. +#define PT_EXIT() do { Stop(); return false; } while (0) + +// Yield protothread till next call to its Run(). +#define PT_YIELD() \ + do { ptYielded = false; _ptLine = __LINE__; case __LINE__: \ + if (!ptYielded) return true; } while (0) + +// Yield protothread until given condition is true. +#define PT_YIELD_UNTIL(condition) \ + do { ptYielded = false; _ptLine = __LINE__; case __LINE__: \ + if (!ptYielded || !(condition)) return true; } while (0) + +#endif // __PROTOTHREAD_H__ \ No newline at end of file