• Stars
    star
    178
  • Rank 214,989 (Top 5 %)
  • Language
    C++
  • License
    MIT License
  • Created about 12 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Protothread.h, a C++ port of Adam Dunkels' protothreads library

Protothread.h, a C++ "port" of Adam Dunkels' protothreads library

Adam Dunkels invented protothreads, a nifty set of C macros for helping write super-light, stackless threads. What protothreads give you is the ability to write procedural, thread-style code, but without the overhead of real threads. The kind of thing embedded programmers normally use switch state machines for.

This is a port of Adam's protothread library to C++. If you're using C++, this might be the way to go, as there are a few advantages over protothreads in C:

  • You can make a Protothread class, so you don't need to pass the struct pt* around everywhere.
  • You can use instance variables where you might have used statics, making your protothreads easy to multi-instance.
  • You can write classes derived from Protothread that add helper variables and macros to read and wait for timers, specific I/O ports, etc.

Okay, so show us an example. Fair call.

Below is a C++-style protothread that implements a simple packet protocol. Each packet has a sync byte, a length byte, n data bytes, and a checksum byte. Packets are only processed if they’re good and complete:

bool UartThread::Run()
{
    PT_BEGIN();

    while (true) {
        // wait for sync byte
        PT_WAIT_UNTIL(ReadByte(ch));
        if (ch == Sync) {
            // read length byte, ensure packet not too big
            PT_WAIT_UNTIL(ReadByte(ch));
            len = ch;
            if (len <= MaxLength) {
                // read n data bytes
                for (i = 0; i < len; i++) {
                    PT_WAIT_UNTIL(ReadByte(ch));
                    data[i] = ch;
                }
                // read checksum, dispatch packet if valid
                PT_WAIT_UNTIL(ReadByte(ch));
                if (ValidChecksum(data, len, ch))
                    Dispatch(data, len);
            }
        }
    }

    PT_END();
}

Not bad, eh? Even with comments it’s much shorter and sweeter than the equivalent state machine version (which, incidentally, is pretty much what the protothread macros expand to):

bool UartThread::Run()
{
    while (true) {
        switch (state) {
        case StateSync:
            if (!ReadByte(ch))
                return true;
            if (ch != Sync)
                break;
            state = StateLength;

        case StateLength:
            if (!ReadByte(ch))
                return true;
            len = ch;
            if (len > MaxLength) {
                state = StateSync;
                break;
            }
            i = 0;
            state = StateData;

        case StateData:
            while (i < len) {
                if (!ReadByte(ch))
                    return true;
                data[i] = ch;
                i++;
            }
            state = StateChecksum;

        case StateChecksum:
            if (!ReadByte(ch))
                return true;
            if (ValidChecksum(data, len, ch))
                Dispatch(data, len);
            state = StateSync;
        }
    }
}

So there you go. I know which version I’d rather write and maintain.

The Protothread.h header file I put together from Adam Dunkels’ C version should have all you need to get started. I’ve left writing a “protothread scheduler” as an exerciser for the reader, as it would be both simple and application- dependent.

Just a final word: I’m not suggesting protothreads are a replacement for threads -- they’re not. But when you need the appearance of threads, or you’re dealing with embedded micros and don’t have screeds of RAM, give them a try.

Read my original blog entry or check out the source.

More Repositories

1

inih

Simple .INI file parser in C, good for embedded systems
C
2,402
star
2

goawk

A POSIX-compliant AWK interpreter written in Go, with CSV support
Go
1,920
star
3

scandir

Better directory iterator and faster os.walk(), now in the Python 3.5 stdlib
Python
529
star
4

pygit

Just enough git (written in Python) to create a repo and push to GitHub
Python
314
star
5

countwords

Playing with counting word frequencies (and performance) in various languages.
Rust
306
star
6

pybktree

Python BK-tree data structure to allow fast querying of "close" matches
Python
169
star
7

ht

Simple hash table implemented in C
C
148
star
8

pyast64

Compile a subset of the Python AST to x64-64 assembler
Python
136
star
9

go-routing

Different approaches to HTTP routing in Go
Go
120
star
10

loxlox

Lox interpreter written in Lox
Python
112
star
11

mugo

Mugo, a toy compiler for a subset of Go that can compile itself
HTML
108
star
12

littlelang

A little language interpreter written in Go
Go
92
star
13

third

Third, a small Forth compiler for 8086 DOS
Forth
75
star
14

go-1brc

My Go solutions to the One Billion Row Challenge
Go
74
star
15

prig

Prig is for Processing Records In Go. Like AWK, but snobbish.
Go
64
star
16

gogit

Just enough of a git client (in Go) to init a repo, commit, and push to GitHub
Go
51
star
17

cdnupload

Upload your site's static files to a directory or CDN, using content-based hashing
Python
50
star
18

web-service-stdlib

Rewrite of Go RESTful API tutorial using only the stdlib
Go
49
star
19

simplelists

Tiny to-do list web app written in Go
Go
48
star
20

pas2go

Pascal to Go converter (converts a subset of Turbo Pascal 5.5)
Pascal
42
star
21

symplate

Symplate, a simple and fast Python template language (NOTE: no longer maintained; use Jinja2 or Mako instead)
Python
30
star
22

nibbleforth

A very compact stack machine (Forth) bytecode
Python
29
star
23

zztgo

Port of ZZT to Go (using a Pascal-to-Go converter)
Go
26
star
24

gosnip

Run small snippets of Go code from the command line
Go
24
star
25

python-pentomino

Pentomino puzzle solver using Python code generation
Python
20
star
26

benhoyt.github.com

Source code for my website
HTML
18
star
27

betterwalk

BetterWalk, a better and faster os.walk() for Python -- DEPRECATED, see my "scandir" project
Python
17
star
28

fe

Bruce Hoyt's Forth Editor (Dad's editor that I grew up coding with)
Forth
16
star
29

namedmutex

namedmutex.py, a simple ctypes wrapper for Win32 named mutexes
Python
15
star
30

soft404

Soft 404 (dead page) detector in Python
Python
13
star
31

io-performance

Code repo for https://benhoyt.com/writings/io-is-no-longer-the-bottleneck/
Go
13
star
32

awkmake

Code to go with my article "The AWK book's 60-line version of Make"
Awk
13
star
33

repike

Rob Pike's simple regex matcher converted to Go
Go
11
star
34

benos

A tiny 32-bit Forth operating system I wrote when I was 16
Forth
8
star
35

counter

Fast hash table for counting short strings in Go
Go
7
star
36

false-forth

A False compiler and interpreter written in ANS Forth
Forth
7
star
37

py-1brc

Optimising the One Billion Row Challenge (1BRC) in Python
Python
5
star
38

mro

MRO is not an ORM - Map Rows to Objects with web.py
Python
2
star
39

snappass-test

Demo of Juju K8s sidecar charm with Pebble
Python
2
star
40

circle

Draw circles using the Bresenham Circle Algorithm in Go
Go
2
star
41

interpspeed

Test interpreter speed of various language VMs
Python
1
star
42

boggle

Boggle solver competition
Python
1
star