 åɤƱˤĤ
С0.6ǤƱͤ˥ޥåɤGUIΥ쥹ݥ󥹤ݤ
Ĥreader/writeråƳͥåȥΥ
ɤλȤС0.5ϰηиˡåɴ֤Ʊμ
ƹͤɬפ롣


 Ʊݥ
gdk_threads_enter()/gdk_threads_leave()Ѥå
	glib/gtk¾Ѥ롣

sigslot.hѤå
	sigslot.hˤsignal/slot¾Ѥ롣

PollEventManagerѤå
	poll()ԤꥹʤϿ٥Ȥνɬפ¾
	Ѥ롣

ThreadPoolѤå
	åɤ֤ʤɤɬפ¾
	롣

ParseBBSMenuJobѤå
	İιΤ¾Ѥ롣

Хåեreader/writerå
	ХåեƤproducer/consumer֤¾Ѥ롣
	producerϥХåեγĥͭǡĹѹΤwriterå
	롣


 ƹͥݥ

 BLOCK or NONBLOCK?
poll()ƥǡȤNONBLOCK⡼ɤɤ߹褦ˤƤ⡢
餯ͥåȥ塢̤ΥǡˤɤȤΤѽФ
η̡CPU٤⤯ʤ᤮뤳Ȥʬää뤿
ͥåȥˤϥ֥å󥰥⡼ɤ̿Ԥ

֥å󥰥⡼ɤǤ̿Ѥ뤿ˤϡͥåȥ
ǡʤåݻƤϤʤʤȤ§ɬפ롣
ȡ֥å˥åԤΥåɤƻϢˤʤäԤ
롣

libghttpasync⡼ɤǻȤˤΤƤǤasync⡼ɤǻȤäƤ
ͳΰĤϡ̿ߤ뤿äsocketclose
ޤХ֥åǤʵΤǤ¸Ƥߤ褦



 DATϤȥ
С0.5ϰϥ󥰥åɤƤDATϤԤäƤ
Ϥˤ롣ͥåȥˡɤ߹ǡХåե
ɵǡڤ()򸫤ĤĤN쥹ܤγoffset
˳ǼȤ٤βϤԤäƤޤȤˤ롣



 DATեιϤȥ

С0.5ϰϰĤΥɽΤ˰ʲΤ褦ʥåɤư
Ƥ

- ͥåȥå(DATեɤ߹)
- 󥰥å(DATեϤ̤GtkTextBuffer˽
  )

ĮBBSʤɤDATľɤߤǤʤǼĤǤϾΥͥåȥ
ɤεǽĤΥåɤʬ򤵤졢ʲΤ褦ˤʤäƤ

- ͥåȥå(HTMLɤ߹)
- Сå(HTMLֵDATեѴ)
- 󥰥å(DATեϤ̤GtkTextBuffer˽
  )

˲äɥåɤʤɤƱ롣


ιƱ褦ʴǼƤС0.6
Ǥϥ󥰥åɤΤߤᡢg_idle_add()Ͽ
ˤꡢˤʻ˰٤500ʲGtkListStoreɲäǤ
ɲäȤѤƤߤΤpriorityΥ塼˥󥰤;Ϥ
ΤΡ줬ճ˰ʤɽǤƱͤμˡɤ⤷



˹ͤ뤳ȤϡBBSThreadǴGUIʬ뤫
ȤȤǤ롣

Ūˤϡʥ桼λؼˤꤽ줬Ѥ٤Ǥˤ˥
Ƥͥåȥɤޤ줿Τå夫ɤ
ʤɤȤˤϤޤạ̈ʤnܤΥ쥹ƤɤʤΤ
ȤȤ˶̣롣ĤޤꡢModel-ViewδطǸViewɬ
ȤModelεǽϡnܤΥ쥹פǽʬȸäƤ褤


ξ硢ꥹȤΥ󥷥ʥǤнʬä
ThreadlistIteratorJavaIteratorݲɽξ硢
ݥåץåפʤɤΤ˥ॢǤ뤳Ȥ˾ޤ

ʤΤǡʲΤ褦ʴݲͽꡣ


class BBSResponse
{
public:
  const char *get_name();
  const char *get_mailto();
  const char *get_date();
  const char *get_id();
  const char *get_message();

  // ʲparsingη̤줿flagsβѡ
  bool is_valid();	// Ȥͭɤ
  bool is_broken();	// 줿쥹ʤtrue
  bool is_deleted();	// 줿쥹ʤtrue(e.g.ĮBBSƩ)
};


class ResponseCursor : public RefCount
{
public:
  // encodingϥ饤Ȥ׵ᡣNULL̵Ѵ
  ResponseCursor(const char *encoding = NULL);

  // ʲreaderå
  int lock();
  int trylock();
  int unlock(int lock_id);

  // λǥ쥹res_numΥ쥹Ǥtrue֤ͥåȥ
  // DATեμǤ⥭å䤽ޤɤ߹ʬ
  // б쥹ޤޤƤtrue֤롣դˡԤäƤФ
  // ǽˤʤʬǤ⡢λǼǽǤʤfalse
  // ܡΤˤƼʤɤΤǡƱres_numξǤ
  // Υ᥽åɤη̤lock()ƤָͭȤʤ롣
  virtual bool has_response(int res_num);

  // 쥹res_numΥ쥹Ƥ֤
  virtual BBSResponse &get_response(int res_num);

  // DATեβϤλƤ뤫ɤ֤finished()
  // trueʻhas_response()falseʥ쥹¸ߤʤΤƱ
  virtual bool finished();

  // DATեβϤʹԤfinished()η̤Ȥtrue
  // ֤郎äȤȯԤsigslotʥ롣
  Signal0 state_changed;


  // ʲDATեι˥ͥåȥȼäˡ
  // ˱ȯԤ륷ʥ롣̩ƱΤ
  // ݤʳ㤤ʤΤǡŬ˽
  // void access_started();
  Signal0 access_started;

  // void access_progressed(size_t data_read, size_t total_len);
  signal2<size_t, size_t> access_progressed;

  // void access_finished();
  Signal0 access_finished;

  // ܡλȯԤ롣
  // void cache_is_dirty();
  Signal0 cache_is_dirty;

  // void access_failed(const char *reason);
  signal1<const char *> access_failed;

  // void access_terminated();
  Signal0 access_terminated;
};


 ͥåȥԶä˸

С0.5ϤʤۤɽŤʤ븶ϡƥȥ
ȥʥ륳ȯԤˤ˹Ԥ뤳ȤˤäͽۤƤ롣

ŪˤϡС0.5ǥåȤΥեǥץ
O_NONBLOCKե饰ꤹ褦ˤpoll(2)ࡽºݤˤGLibΥ
٥ȥ롼סɤǡnon-blockɤɤȤ
Ѥǡ̿λʳǤTCPκǾѥåȥ˶
ñ̤ǥǡɤ߹ߤԤ褦ˤʤäƤ㤨СĹN
Υǡɤ߹֤̿λԤġפ褦pollingФ
ϲǤΤ¿ʬ¸ߤʤΤǤΤޤޤǤϲǤʤ

(1) åfdɤǤ륹åAfdǤpoll׵ᤷ
    pthread_cond_wait()

(2) pollingåɤˤpoll(2)fdʥåȤؤ(1000ХȤ餤
    )ǡΤpthread_cond_signal()ǥåɤ򵯤

(3) åAåfdǡɤ(1000ХȤ餤)ɤߡ
    ̿λǤʤС(1)򷫤֤

Ρghttpasync⡼ɤȤ褦ˤˡchunksizeꤷƤ
ʤä(ǥեȤ1000ȤƤ)˵äƤΤƱݤ
Τϥʥʲˡʤ

餯O_NONBLOCKߤʳˡϤʤO_NONBLOCKˤƤ
ͳtimeoutμ¸ʤΤǡ̤ˡǼ¸ɬפ롣

(̤Ȼפ)libghttpǤΥͥåȥϰʲμǹԤ롣

(1) ̾β
(2) socket(2)
(3) connect(2)
(4) ̿
(5) close(2)

⡢(1)ϱ(̾ȤʤȤʬʤ)Ĺ
֥å뤬ޡȤʲˡʤɤˡϡ̸
ޡѤƤٻ֤ФäUNIXʥäSIGINTǻߤ
äˡΤ褦pthreadUNIXʥϴpthread_kill()
ȤϤΤǤĤƤߤ褦

(2)(5)Ĺ֥֥å뤳ȤϤʤȻפäɤ

(3)ǥ֥åȤʤỴξˤꥷƥ٥Ǥ
   ॢȤޤǿʬñ̤λ֤ݤ롣

(4)̿٤Ȥ˥֥åƤޤΤܼŪ򤱤ʤ

O_NONBLOCKˤꡢ(3)(4)Ǥ롽С0.5ϤޤǤ(3)λ
ǤO_NONBLOCKꤷƤʤäġġ

O_NONBLOCKͳԶϸŪˤ(4)ǤȸäɤΤǡ(3)
O_NONBLOCKǼ¹Ԥ(4)O_NONBLOCKѹȤˡ
ꤽäˡHTTPΥ쥹ݥ󥹥إåɤ߹߽λ
ǹͤʤ顢RangeupdateξΥåȽ
O_NONBLOCKѹΤɤ褦ʵ롣
̿ϸO_NONBLOCKƤ֥åʤΤLinuxλͤʤ
ġġ


Ǥޤäġ
פΤäȡsigslotΥʥϥɥäƤơġ
destructorgdk_threads_enter()褦WorkerJobcommit
gdk_threads_enter()ThreadPool::commit()ƤϤʤʤ


񤭹ߵǽμˤĤ
ǼĤμˤäƽ񤭹߻νϰۤʤ롣ϷǼĤμ
OchushaBulletinBoardΥ֥饹Ȥʬ뤳ȤǼäƤ
ڤΤǻߤ᤿ɤ߹ߤƱͤ˽񤭹ߤ򤹤뵡ǽ󶡤
֥Ȥ֤᥽åɤBBSThreadѰդGUIϤΥ֥Ȥ
Ȥäƽ񤭹߽ꤹȤǼ롣

class PostResponseAgent
{
public:
  void try_post(const char *name, const char *mailto, const char *body);
  void retry_post();

  void set_2ch_be_session_id(const char *id);
  void set_2ch_viewer_session_id(const char *id);

  signal1<PostResponseAgent> post_finished;
  signal2<PostResponseAgent, const char *> post_failed;
  signal2<PostResponseAgent, const char *> check_cookie;
};

ʴˤʤ롣(Կ¤Ȥ)Ƽåɬפ
᥽åɤɲä롣
