IERO
Модератор
Карма: 8
Сообщений: 432
Debian Lenny
|
|
« : 02 Марта 2009, 19:16:05 » |
|
нужно написать класс(или два), работающий с raw-сокетом(чтение и запись). причем писать и читать надо независмо, т.е. не дожидаясь завершения записи чтобы начать оттуда читать. на си это реализовалось просто парой потоков работавших с одним сокетом. а тут нужно завернгуть все в класс. в связи с этим вопрос - стоит ли вообще класс разносить на 2 потока или лучше сделать 2 класса и объект каждого пускать в своем потоке? и если можно так делать - то лучше второй поток создавать в конструкторе, или отдельным методом?
|
|
|
Записан
|
|
|
|
Леголегс
|
Я бы начал примерно так: class My_socket { SOCKET socket; Mutex mutex; void write(...); void read(...); }; void My_socket::write(...) { mutex_wait(mutex); int r = write(socket,...); mutex_release(mutex); if (! r) throw("Нимагу писать фсокет!"); } void My_socket::read(...) { mutex_wait(mutex); int r = read(socket,...); mutex_release(mutex); if (! r) throw("Нимагу фтыкать сокет!"); } /*******************/ class My_thread { My_socket * my_socket; Thread thread; My_thread(My_socket * new_my_socket):my_socket(new_my_socket),thread(0) {}; ~My_thread() { if (thread) terminate(thread);}; void launch(); };
void My_thread::launch() { thread = create_thread(...); if (!thread) throw("хрентам"); }
|
|
|
Записан
|
|
|
|
IERO
Модератор
Карма: 8
Сообщений: 432
Debian Lenny
|
я не фрагмент кода спрашиваю, а концепцию. и откройте секрет двоеточия необразованому человеку. и коментов можно добавить . ничего не ясно в потоке чистого сознания.
|
|
|
Записан
|
|
|
|
IERO
Модератор
Карма: 8
Сообщений: 432
Debian Lenny
|
class Pinger { pthread_t thread; Socket socket; Cycle* cyclelist; CycleResult * result; Pinger(); Add(Cycle); ExecCycle(); ReadSocket(); }
Pinger::Pinger() { socket=..... thread =pthread_create(§hread, ...); ..... }
int secthread { while(1) { read(socket); } } я имел ввиду нечто вроде этого. и дальше основной поток может мучать Pinger как угодно ,а созданый внутри класса поток все работает и работает... или это глупо и плохо?
|
|
|
Записан
|
|
|
|
Леголегс
|
Ну что-то вроде этого я и имел ввиду. Надо учесть ряд моментов: 1. возможно, захочется юзать в потоке членов класса. Это нормально и стесняться тут нечего надо, само собой передать в secthread указатель на Pinger (типа pthread_create(&thread, NULL, secthread, this)). 2. Имей однако ввиду, что при 1. надо быть осторожным, трогая из основного потока содержимое Pinger. Сказав 'A', говори 'B'. Почти наверняка от синхронизации ты не отвертишься. 3. Естественно само собой разумеется надо в деструкторе мочить поток. Мочить можно по-плохому (man pthread_cancel) или по хорошему (послать так или иначе сообщение и ждать выхода с помощью pthread_join). 4. И если будешь юзать исключения, то try/catch должны быть в том же потоке, что и throw. Не знаю пока как в gcc, а в борландбилдере нарушение этого правила вызывало ужасные сообщения об ошибках.
|
|
|
Записан
|
|
|
|
IERO
Модератор
Карма: 8
Сообщений: 432
Debian Lenny
|
1.можно второй поток сделать членом класса, к тому же приватным в моем случае. спасибо за идею. 2. в момент когда сокету делают read, в него вполне можно вторым потоком делать write (по крайней мере с тцп/юдп такое катит). поэтому мьютексы в этом фрагменте вроде как лишние.
|
|
|
Записан
|
|
|
|
IERO
Модератор
Карма: 8
Сообщений: 432
Debian Lenny
ОС:
Linux
Браузер:
Opera 9.52
|
извиняюсь за некромантию, дубль 2. вопрос схожий, но поинтересней.
есть класс A, внутри которого существует список объектов класса B. class A{ .......... list<B*> B_List; ............... } class B{ short m_die_status; static void * FstThread(void *); } класс B имеет в конструкторе примерно такое: B::B(....) { if( ( pthread_create ( &main_thr, NULL, & (B::FstThread),this ) ) !=0) m_die_status=1; } в деструкторе B::~B(....) { m_die_status=1; pthread_join (main_thr, NULL ); } при этом осознание что пора заканчиваться наступает в потоке который FstThread. возникает вопрос - каким образом своевремено чистить B_List от тех объектов потоки которых уже отработали? или данная концепция изначально порочна и лучше в классе A создавать нитки, и внутри ниток создавать уже объекты, и как можно отслеживать в таком случае?
|
|
|
Записан
|
|
|
|
Леголегс
|
У тебя m_die_status что означает? "насяльника, я не смог стартовать, добей меня" или "щас сдохну, сдохну, сдохну, честноеслово, щас ещё чуть чуть и сдохну..." Ты определись, да. И ещё. разве твои потоки могут дохнуть сами? вроде они должны работать пока их не прибьют. А вообще, ведёщие собаководы вроде как передают в таких случаях ссылку на контейнер в экземпляры.
|
|
|
Записан
|
|
|
|
IERO
Модератор
Карма: 8
Сообщений: 432
Debian Lenny
ОС:
Windows XP
Браузер:
MS Internet Explorer 6.0
|
m_die_status по моим арсчетам может работать в 2 стороны. по его значению понимается успешность вызова конструктора объекта(проверяется значение после создания), и по нему же помирает второй поток. про ссылку на контейнер это как? передавать указатель на лист, и в деструкторе приказывать мочить элемент в листе? упд: маскировка работает
|
|
|
Записан
|
|
|
|
|