The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

Пример использования тредов. (example threads)


<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>
Ключевые слова: example, threads,  (найти похожие документы)
Date: Mon, 4 Mar 2002 20:43:56 +0000 (UTC) From: Vladimir Dozen <dozen@osw.com.ru> Newsgroups: fido7.ru.unix.prog Subject: Пример использования тредов. > > В-третьих, возможно самому родить простые кооперативные нити > А по подробнее, what's it? Тебе это не подойдет, у тебя много параллельных read/write, а у кооперативных нитей нить-то на самом деле одна, и если она заснула на write(), то и остальные спят. Для общего развития можешь посмотреть листинг. Список нитей сделан страшно криво, но это был просто proof of concept. Собрано под фряху, под линуксом надо заменить макрос SET_STACK_JB;
#include <iostream> #include <stdexcept> #include <setjmp.h> #include <sys/types.h> #include <dirent.h> using namespace std; // thread identificator type typedef int jmpthread_t; // maximum threads runned so far and current number of threads int maxthread = 0; int cntthread = 0; jmpthread_t curthread = -1; // thread contextes jmp_buf threads[128]; // active (not terminated) threads has true in this bool threads_used[128]; // thread starting routines addresses (see jmpthread_start()) typedef void(*jmpthread_start_t)(jmpthread_t); jmpthread_start_t threads_start[128]; // context of main thread jmp_buf mainthread; #define stack_location(n) { char c; std::cout << tid \ << ":stack for " << n << " is at " << std::hex << (void*)&c << std::endl; } #define notify(msg,val) std::cout << tid << ":" << msg \ << " value:" << val << std::endl /** * Machine-dependent stuff. * Taken from FreeBSD:/usr/src/libc_r/uthreads/pthreads_private.h */ #define SET_STACK_JB(jb,stack) (jb)[0]._jb[2] = (int)(stack) /** * Reschedules a thread to run. * Randomly chooses a thread to execute. */ void jmpthread_sched(jmpthread_t tid) { assert(cntthread>0); int ntid; while(true) { ntid = (int)(drand48()*maxthread); if( threads_used[ntid] == true ) break; } curthread = ntid; longjmp(threads[ntid],1); } /** * Starts new thread. * @return Thread id of newly created thread. * @param start Address of thread procedure. * @param stacksz Stack size for thread. */ jmpthread_t jmpthread_create(void (*start)(jmpthread_t),int stacksz=8192) { ++maxthread; ++cntthread; jmpthread_t iam = maxthread-1; threads_used[iam] = true; int rc = setjmp(threads[iam]); if( rc == 0 ) { // setup new stack char* stk = (char*)malloc(stacksz+sizeof(jmp_buf)); SET_STACK_JB(threads[iam],stk+stacksz); threads_start[iam] = start; return iam; } else if( rc == 1 ) { // run thread; we have moved stack, so we cannot use address // of start from parameters and 'iam' from stack; use saved // address and curthread instead threads_start[curthread](curthread); } else { // unexpected error exit(1); } return -1; } /** * Stops thread. */ void jmpthread_exit(jmpthread_t tid) { threads_used[tid] = false; --cntthread; // no more threads; return to main routine if( cntthread == 0 ) longjmp(mainthread,1); jmpthread_sched(-1); } /** * Passes control back to scheduler. * @param tid Thread id of current thread. */ void jmpthread_yield(jmpthread_t tid) { // if we called from main routing, just pick a thread randomly if( tid < 0 ) { jmpthread_sched(tid); return; } // save context int rc = setjmp(threads[tid]); if( rc == 0 ) { // saved previous active thread; activate another // choose random thread from list jmpthread_sched(tid); } else if( rc == 1 ) { // just reactivated return; } else { // oops; error? exit(1); } } void f1(jmpthread_t tid) { stack_location("f1"); // to check we have correct stack pointer int localdata = tid; DIR* dir; notify("entered f1",localdata); dir = opendir("/etc"); jmpthread_yield(tid); struct dirent* de; while( (de = readdir(dir)) != 0 ) { notify(de->d_name,localdata); jmpthread_yield(tid); } closedir(dir); notify("leaving f1",localdata); jmpthread_exit(tid); } void my_main(jmpthread_t tid) { stack_location("my_main"); // thread id of created thread jmpthread_t child = 0; notify("entered my_main",child); for( int i=0; i<4; ++i ) { child = jmpthread_create(f1); notify("created thread",child); } notify("leaving my_main",child); jmpthread_exit(tid); } int main() { if( setjmp(mainthread) == 0 ) { // schedule threads jmpthread_t tid = -1; jmpthread_t child = 0; child = jmpthread_create(my_main); notify("created thread",child); while( cntthread > 0 ) jmpthread_yield(-1); } else { // called from jmpthread_exit: no more threads } return 0; }
-- dozen @ home

<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>

 Добавить комментарий
Имя:
E-Mail:
Заголовок:
Текст:




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру