Reading Protothreads: Simplifying Event-Driven Programming of Memory-Constrained Embedded Systems

TL;DR

Event-Driven から coroutine ベースの実装にするとメモリーオーバーヘッドが下がって、コードも短かく書ける。

以下論文の内容です。

Abstract

Protothreads

Scheduling

Implementation

大きく分けて次のアプローチがある。

  1. preprocessor based implementation
  2. assembly language based implementation
  3. setjmp and longjmp based implementation
  4. stackful implementation

preprocessor based implementation

/** local continuation implemented with the GCC labels-as-values C extension */
#ifdef(__GNUC__)
typedef void * lc_t;
#define LC_INIT(c)     c = NULL
#define LC_RESUME(c)   if (c) goto *c
#define LC_SET(c)      { __label__ r; r: c = &&r; }
#define LC_END(c)
#endif

/** local continuation implemented with the C switch statement */
#ifndef(__GNUC__)
typedef unsigned short lc_t;
#define LC_INIT(c)     c = 0;
#define LC_RESUME(c)   switch(c) { case 0:
#define LC_SET(c)      c = __LINE__; case __LINE__:
#define LC_END(c)      }
#endif


/** protothread type */
struct pt { lc_t lc };

/** protothread state definitions */
#define PT_WAITING 0
#define PT_EXITED  1
#define PT_ENDED   2

/** protothread macros */
#define PT_INIT(pt)  LC_INIT(pt->lc)
#define PT_BEGIN(pt) LC_RESUME(pt->lc)
#define PT_END(pt)   LC_END(pt->lc); \ return PT_ENDED
#define PT_EXIT(pt)  return PT_EXITED
#define PT_WAIT_UNTIL(pt, c) \
        LC_SET(pt->lc); \
        if (!c) return PT_WAITING
#define PT_BEGIN(pt) \
            { int yielded = 1; \
              LC_RESUME(pt->lc)
#define PT_YIELD(pt) \
              yielded = 0; \
              PT_WAIT_UNTIL(pt, yielded)
#define PT_END(pt) \
              LC_END(pt->lc); \
              return PT_ENDED; }
#define PT_SPAWN(pt, child, thread) \
            PT_INIT(child); \
            PT_WAIT_UNTIL(pt, thread != PT_WAITING)

assembly language based implementation

setjmp and longjmp based implementation

stackful implementation

Comments

comments powered by Disqus