The wiki doesn't let me check stuff off so here it is.
main list
[x] settable max queue depth and enforcement thereof
[x] invent register noodles (only hold one sample, has initial value, never blocks for input or output)
[x] make blocks continually work until their outputs are full or their inputs are empty
[x] add typedef int sample_t and use that everywhere for samples, for now
[x] make sure that lock_guard blocks at construction time when taking the mutex
[x] figure out how to make the mutex code in Ports be a no-op for RNoodles in a non-dumb way
[ ] validate queue max values
[ ] add a mutex for the debug function: perhaps use vsprintf to format to a buffer, then mutex-wrap a single function call to blast that string to stderr
[x] rename please to available
[ ] modify Block::work semantics a bit
[ ] add required function bool Block::could_do_work(void)
[ ] Block::work should now just immediately do work and exit
[ ] now, in Graph::run, there should be a loop: while (block->could_do_work()) { block->work() }
[ ] update documentation of this stuff so Brett doesn't get confused
[x] replace instances of NULL with nullptr
[x] in Graph::dumpGraph, dumpNoodles, assert that both are not null AND that neither is not null
[x] use StrPool in Block::name so we don't leak
[ ] add color functionality to debug function to make it easier to identify stuff
[ ] put everything into a namespace
type system
[x] make a branch for this!
[ ] invent class InputPort<T> and class OutputPort<T> (probably subclassed from Port<T>)
[ ] move putget etc. into class InputPort<T> and class OutputPort<T>
[ ] change class Noodle to class Noodle<T> (use queue<T> with same type param)
[ ] class Noodle<T>'s from and to should now be OutputPort<T> * or InputPort<T> * pointers (no more Block * + index nonsense!)
[ ] make class InputPorts and class OutputPorts have operator[const char *] which returns a reference/pointer to the Port instance with the given name (can throw exceptions of course)
[ ] possibly rename InputPorts to InputPortSet etc.
[ ] for faster access, a block subclass work function could have a static local variable: static auto in_port = inputs["theinput"] and thenceforth use in_port directly
[ ] what if we put storage of the individual InputPort and OutputPort classes into the Block subclasss implementation?
pro: no need to deal with storage in InputPorts or OutputPorts
pro: no more string associative array nonsense; the ports are just named member variables
pro: maybe we won't need InputPorts and OutputPorts classes at all anymore
con: how do we connect noodles at setup time? would blocks' Ports need to be public so we can get a pointer and connect up the noodle?
invent class Connector; it will have one static instance with a static function that sets up all the noodles and stuff; every Block subclass will need to include friend class Connector (ugh)
we need to be extremely careful that the only thing Connector ever does with the InputPorts and OutputPorts is connect them up, otherwise we could really screw up our thread safety assumptions
also we could possibly make class Graph be subclassed for individual 'graph setups', and have the class MyGraph subclass's function do the connecting
possible solution to threading worries: make a strictly enforced "setup time" vs "run time" notion
con: probably not possible to get input/output port names at runtime (unless there's a super secret c++ abi thing for this, which I doubt)
feedback/testing
[x] implement a feedback example
[ ] test it and see how badly broken it is
scheduler
[x] check if STL queue is guaranteed to be thread-safe
[x] implement mutexes?
[x] invent class Scheduler (abstract) with subclasses:
[x] RoundRobin
[ ] Threaded
[ ] Interactive: GUI-driven "scheduler" with indicators showing what's in each noodle, which blocks are "blocked", and buttons to make blocks do work
[ ] spawn thread for each block
[ ] sleep when unable to do work (this_thread.sleep_for or this_thread.yield)
[ ] benchmark performance
[x] compare boost::lockfree::spsc_queue and a mutex-wrapped std::queue
[ ] keep all Scheduler subclasses in Scheduler.h, but:
[ ] move class RoundRobinScheduler to RoundRobinScheduler.cpp
[ ] move class ThreadedScheduler to ThreadedScheduler.cpp
[ ] move class InteractiveScheduler to InteractiveScheduler.cpp
[ ] update Makefile
interactive GUI scheduler
[ ] library: easy drawing
[ ] Cairo
[ ] library: GUI management
[ ] GTK
[ ] visuals
[ ] draw the graph's blocks as rectangles
[ ] draw the blocks' ports on the sides of the rectangles
[ ] draw the noodles as rectangles with arrows connecting them to ports
[ ] show type information on noodles and ports
[ ] show noodle contents and fill level (%)
[ ] show an indicator on each block showing whether it can currently do work
[ ] functionality
[ ] click on a block to make it run once (if it can do work)
[ ] double-click a block make it run as many times as possible
[ ] spacebar to automatically choose a runnable block and run it once
[ ] allow blocks/noodles to be dragged around because it'll probably be too hard to automatically place them in a sensible manner without overlaps or stupid stuff like that
[ ] convenience feature: remember user's block/noodle placement between runs
unit tests
[ ] add unit test to make sure that the mutexes actually work
The wiki doesn't let me check stuff off so here it is.
main list
typedef int sample_t
and use that everywhere for samples, for nowlock_guard
blocks at construction time when taking the mutexPorts
be a no-op forRNoodles
in a non-dumb waydebug
function: perhaps usevsprintf
to format to a buffer, then mutex-wrap a single function call to blast that string to stderrplease
toavailable
Block::work
semantics a bitbool Block::could_do_work(void)
Block::work
should now just immediately do work and exitGraph::run
, there should be a loop:while (block->could_do_work()) { block->work() }
NULL
withnullptr
Graph::dumpGraph
,dumpNoodles
, assert that both are not null AND that neither is not nullStrPool
inBlock::name
so we don't leakdebug
function to make it easier to identify stufftype system
class InputPort<T>
andclass OutputPort<T>
(probably subclassed fromPort<T>
)put
get
etc. intoclass InputPort<T>
andclass OutputPort<T>
class Noodle
toclass Noodle<T>
(usequeue<T>
with same type param)class Noodle<T>
'sfrom
andto
should now beOutputPort<T> *
orInputPort<T> *
pointers (no moreBlock *
+ index nonsense!)class InputPorts
andclass OutputPorts
haveoperator[const char *]
which returns a reference/pointer to thePort
instance with the given name (can throw exceptions of course)InputPorts
toInputPortSet
etc.work
function could have a static local variable:static auto in_port = inputs["theinput"]
and thenceforth usein_port
directlyInputPort
andOutputPort
classes into theBlock
subclasss implementation?InputPorts
orOutputPorts
InputPorts
andOutputPorts
classes at all anymorePort
s need to be public so we can get a pointer and connect up the noodle?class Connector
; it will have one static instance with a static function that sets up all the noodles and stuff; everyBlock
subclass will need to includefriend class Connector
(ugh)Connector
ever does with theInputPort
s andOutputPort
s is connect them up, otherwise we could really screw up our thread safety assumptionsclass Graph
be subclassed for individual 'graph setups', and have theclass MyGraph
subclass's function do the connectingfeedback/testing
scheduler
class Scheduler
(abstract) with subclasses:RoundRobin
Threaded
Interactive
: GUI-driven "scheduler" with indicators showing what's in each noodle, which blocks are "blocked", and buttons to make blocks do workthis_thread.sleep_for
orthis_thread.yield
)boost::lockfree::spsc_queue
and a mutex-wrappedstd::queue
Scheduler
subclasses inScheduler.h
, but:class RoundRobinScheduler
toRoundRobinScheduler.cpp
class ThreadedScheduler
toThreadedScheduler.cpp
class InteractiveScheduler
toInteractiveScheduler.cpp
Makefile
interactive GUI scheduler
unit tests