Test 1. The multitasking core. #include "usual.hpp" #include #include "task.hpp" bool done= FALSE; void task1 (void* a) { int loop= 100; while (loop--) cout << "I'm here!\n"; done= TRUE; } /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */ static void dummy(){} static long two_count; void task2 (void* a) { while (!done) { for (int loop= 0; loop < 10; loop++) dummy(); //delay two_count++; } } /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */ int _stack= 30000; //used by Zortech to set stack size main() { unsigned st[3000]; /* Zortech's Large Model uses seperate stack and data segments, so I could put the task's stack anywhere. However, the system crashed somewhere in the ostream operator<< function on my first try, when the stack was in the data segment. Making the stacks auto variables puts the stack somewhere in the real stack. I want to be able to put stacks in the heap, but gotta watch out for existing code in the library. */ task t1 (task1, 2, st, 1024); task t2 (task2, 2, st+512, 1024); scheduler(); cout << "two_count= " << two_count << "\n"; //prove it did something } ============================================================================= Test 2. Semaphores to insure mutual exclusion. Two tasks are both using DOS. #include "usual.hpp" #include #include "task.hpp" #include "sem.hpp" bool done= FALSE; semaphore DOS; void task1 (void* a) { int loop= 100; while (loop--) { DOS.wait(); //gain exclusive access cout << "I'm here!\n"; DOS.signal(); //release } done= TRUE; } void task1b (void* a) { // do this the same as the first one, but use a resource lock instead. int loop= 80; while (loop--) { resource_lock x(DOS); cout << "I'm there!\n"; // any exit from this block causes the lock to be released, // with very little room for programmer error. } } /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */ static void dummy(){} static long two_count; void task2 (void* a) { while (!done) { for (int loop= 0; loop < 10; loop++) dummy(); //delay two_count++; } } /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */ int _stack= 30000; //used by Zortech to set stack size main() { unsigned st1[512],st2[512],st3[512]; task t1 (task1, 2, st1, 1024); task t2 (task1b, 2, st2, 1024); task t3 (task2, 2, st3, 1024); scheduler(); cout << "two_count= " << two_count << "\n"; } ============================================================================= Test 3. "Hello World" the hard way. This is a test of messages. It shows how several tasks can pass data around. Specificly, one task is reading from and two tasks are writing to a shared message buffer. Task1 prints whatever it gets. The hard part is shutting down task1 when the other tasks are done. The last one to finish must do so. So task1 itself keeps track of how many users it has, and shuts down itself when the last one is finished. #include "usual.hpp" #include #include "task.hpp" #include "sem.hpp" #include "mess.hpp" message m1; //strings for the print server void task1 (void* a) // A print server { char* s; int user_count= 0; for (;;) { m1 >> s; if (*s == '#') { m1.done(); user_count++; //new client logged in } else if (*s == '*') { m1.done(); user_count--; if (user_count == 0) break; //all done } else { //something to print cout << s; m1.done(); } } } /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */ void task2 (void* a) { m1 << "#"; m1 << "Hello from task 2\n"; m1 << "Hello again from task 2!\n"; m1 << "*"; } /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */ void task3 (void* a) { m1 << "#"; m1 << "Hello from task 3\n"; m1 << "Hello again from task 3!\n"; m1 << "*"; } /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */ int _stack= 30000; //used by Zortech to set stack size main() { unsigned st1[512],st2[512],st3[512]; task t1 (task1, 2, st1, 1024); task t2 (task2, 2, st2, 1024); task t3 (task3, 2, st3, 1024); scheduler(); } ============================================================================= Test 4. Pipes and child tasks. This shows one reader and two writers on a pipe. All three tasks are child tasks of another, which creates the pipe and all tasks that use it. This is a more typical situation than the other tests. #include "usual.hpp" #include #include "task.hpp" #include "sem.hpp" #include "mess.hpp" #include "pipe.hpp" #include //need strlen() static char pipe_buf[100]; pipe P (pipe_buf, sizeof pipe_buf); semaphore master(0); //used so master task can wait for sub-tasks to finish /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */ void task1 (pipe_reader* p) { char c; /* loop until the task is killed. When the task is killed, finish printing what is in the pipe. Also, drop out if receive() fails which means the pipe was destroyed. */ while (!(active_task->iskilled() && p->contents()==0) && p->receive (&c, 1)) cout.put(c); } /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */ void task2 (pipe_writer* p) { static char* strings[]= { "This is task2 reporting in\n", "Task2 is still on the line\n", "Task2 sending third string\n", "Task2 running out of things to say\n", "This is task2 again, really having a hard time coming up with material\n" "Task2 saying bye-bye\n", NULL }; for (int loop= 0; strings[loop]; loop++) p->send(strings[loop], strlen(strings[loop])); master.signal(); //inform master that I'm done } /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */ void task3 (pipe_writer* p) { static char* strings[]= { "This is task3 reporting in\n", "Task3 is still on the line\n", "Task3 sending third string\n", "Task3 running out of things to say\n", "This is task3 again, really having a hard time coming up with material\n" "Task3 saying bye-bye\n", NULL }; for (int loop= 0; strings[loop]; loop++) p->send(strings[loop], strlen(strings[loop])); master.signal(); //inform master that I'm done } /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */ void master_task (void*) { preemptable(FALSE); unsigned st1[512],st2[512],st3[512]; //stacks static char pipe_buf[100]; pipe P (pipe_buf, sizeof pipe_buf); task t1 (task1, 2, st1, 1024, (pipe_reader*)&P); task t2 (task2, 2, st2, 1024, (pipe_writer*)&P); task t3 (task3, 2, st3, 1024, (pipe_writer*)&P); master.wait(); //wait for one writer to finish master.wait(); //wait for other writer to finish } /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */ int _stack= 30000; //used by Zortech to set stack size main() { unsigned stack_space[2048]; task master (master_task, 20, stack_space, sizeof stack_space); scheduler(); }