blob: 199e72c9adc88464f866e498763b800855b4759f [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- IOChannel.cpp -------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "IOChannel.h"
11
12#include <map>
13
Eli Friedmana382d472010-06-09 09:50:17 +000014#include "lldb/API/SBCommandInterpreter.h"
15#include "lldb/API/SBDebugger.h"
16#include "lldb/API/SBError.h"
17#include "lldb/API/SBEvent.h"
18#include "lldb/API/SBFileSpec.h"
19#include "lldb/API/SBHostOS.h"
20#include "lldb/API/SBListener.h"
21#include "lldb/API/SBStringList.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022
Eli Friedman07b16272010-06-09 19:11:30 +000023#include <string.h>
24#include <limits.h>
25
Chris Lattner30fdc8d2010-06-08 16:52:24 +000026using namespace lldb;
27
28typedef std::map<EditLine *, std::string> PromptMap;
29const char *g_default_prompt = "(lldb) ";
30PromptMap g_prompt_map;
31
Caroline Ticefe1bdf22011-05-04 16:44:57 +000032// Printing the following string causes libedit to back up to the beginning of the line & blank it out.
33const char undo_prompt_string[4] = { (char) 13, (char) 27, (char) 91, (char) 75};
34
Chris Lattner30fdc8d2010-06-08 16:52:24 +000035static const char*
36el_prompt(EditLine *el)
37{
38 PromptMap::const_iterator pos = g_prompt_map.find (el);
39 if (pos == g_prompt_map.end())
40 return g_default_prompt;
41 return pos->second.c_str();
42}
43
44const char *
45IOChannel::GetPrompt ()
46{
47 PromptMap::const_iterator pos = g_prompt_map.find (m_edit_line);
48 if (pos == g_prompt_map.end())
49 return g_default_prompt;
50 return pos->second.c_str();
51}
52
53unsigned char
54IOChannel::ElCompletionFn (EditLine *e, int ch)
55{
56 IOChannel *io_channel;
57 if (el_get(e, EL_CLIENTDATA, &io_channel) == 0)
58 {
59 return io_channel->HandleCompletion (e, ch);
60 }
61 else
62 {
63 return CC_ERROR;
64 }
65}
66
67unsigned char
68IOChannel::HandleCompletion (EditLine *e, int ch)
69{
70 assert (e == m_edit_line);
71
72 const LineInfo *line_info = el_line(m_edit_line);
73 SBStringList completions;
Greg Claytonc982c762010-07-09 20:39:50 +000074 int page_size = 40;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000075
Greg Clayton66111032010-06-23 01:19:29 +000076 int num_completions = m_driver->GetDebugger().GetCommandInterpreter().HandleCompletion (line_info->buffer,
77 line_info->cursor,
78 line_info->lastchar,
79 0,
80 -1,
81 completions);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000082
83 if (num_completions == -1)
84 {
85 el_insertstr (m_edit_line, m_completion_key);
86 return CC_REDISPLAY;
87 }
88
89 // If we get a longer match display that first.
90 const char *completion_str = completions.GetStringAtIndex(0);
91 if (completion_str != NULL && *completion_str != '\0')
92 {
93 el_insertstr (m_edit_line, completion_str);
94 return CC_REDISPLAY;
95 }
96
97 if (num_completions > 1)
98 {
99 const char *comment = "\nAvailable completions:";
100
101 int num_elements = num_completions + 1;
Caroline Tice969ed3d2011-05-02 20:41:46 +0000102 OutWrite(comment, strlen (comment), NO_ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000103 if (num_completions < page_size)
104 {
105 for (int i = 1; i < num_elements; i++)
106 {
Greg Claytonb1320972010-07-14 00:18:15 +0000107 completion_str = completions.GetStringAtIndex(i);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000108 OutWrite("\n\t", 2, NO_ASYNC);
109 OutWrite(completion_str, strlen (completion_str), NO_ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000110 }
Caroline Tice969ed3d2011-05-02 20:41:46 +0000111 OutWrite ("\n", 1, NO_ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000112 }
113 else
114 {
115 int cur_pos = 1;
116 char reply;
117 int got_char;
118 while (cur_pos < num_elements)
119 {
120 int endpoint = cur_pos + page_size;
121 if (endpoint > num_elements)
122 endpoint = num_elements;
123 for (; cur_pos < endpoint; cur_pos++)
124 {
Greg Claytonb1320972010-07-14 00:18:15 +0000125 completion_str = completions.GetStringAtIndex(cur_pos);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000126 OutWrite("\n\t", 2, NO_ASYNC);
127 OutWrite(completion_str, strlen (completion_str), NO_ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000128 }
129
130 if (cur_pos >= num_elements)
131 {
Caroline Tice969ed3d2011-05-02 20:41:46 +0000132 OutWrite("\n", 1, NO_ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000133 break;
134 }
135
Caroline Tice969ed3d2011-05-02 20:41:46 +0000136 OutWrite("\nMore (Y/n/a): ", strlen ("\nMore (Y/n/a): "), NO_ASYNC);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000137 reply = 'n';
138 got_char = el_getc(m_edit_line, &reply);
139 if (got_char == -1 || reply == 'n')
140 break;
141 if (reply == 'a')
142 page_size = num_elements - cur_pos;
143 }
144 }
145
146 }
147
148 if (num_completions == 0)
149 return CC_REFRESH_BEEP;
150 else
151 return CC_REDISPLAY;
152}
153
154IOChannel::IOChannel
155(
Caroline Tice969ed3d2011-05-02 20:41:46 +0000156 FILE *editline_in,
157 FILE *editline_out,
158 FILE *out,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000159 FILE *err,
160 Driver *driver
161) :
162 SBBroadcaster ("IOChannel"),
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000163 m_output_mutex (),
164 m_enter_elgets_time (),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000165 m_driver (driver),
166 m_read_thread (LLDB_INVALID_HOST_THREAD),
167 m_read_thread_should_exit (false),
168 m_out_file (out),
169 m_err_file (err),
Greg Claytonc982c762010-07-09 20:39:50 +0000170 m_command_queue (),
171 m_completion_key ("\t"),
Caroline Tice969ed3d2011-05-02 20:41:46 +0000172 m_edit_line (::el_init (SBHostOS::GetProgramFileSpec().GetFilename(), editline_in, editline_out, editline_out)),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000173 m_history (history_init()),
Greg Claytonc982c762010-07-09 20:39:50 +0000174 m_history_event(),
Caroline Tice969ed3d2011-05-02 20:41:46 +0000175 m_getting_command (false),
176 m_expecting_prompt (false),
Caroline Tice86a73f92011-05-03 20:53:11 +0000177 m_prompt_str (),
178 m_refresh_request_pending (false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000179{
180 assert (m_edit_line);
181 ::el_set (m_edit_line, EL_PROMPT, el_prompt);
182 ::el_set (m_edit_line, EL_EDITOR, "emacs");
183 ::el_set (m_edit_line, EL_HIST, history, m_history);
184
185 // Source $PWD/.editrc then $HOME/.editrc
186 ::el_source (m_edit_line, NULL);
187
Caroline Tice0de8d452011-05-04 21:39:02 +0000188 el_set (m_edit_line, EL_ADDFN, "lldb_complete",
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000189 "LLDB completion function",
190 IOChannel::ElCompletionFn);
Caroline Tice0de8d452011-05-04 21:39:02 +0000191 el_set (m_edit_line, EL_BIND, m_completion_key, "lldb_complete", NULL);
192 el_set (m_edit_line, EL_BIND, "^r", "em-inc-search-prev", NULL); // Cycle through backwards search, entering string
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000193 el_set (m_edit_line, EL_CLIENTDATA, this);
194
195 assert (m_history);
196 ::history (m_history, &m_history_event, H_SETSIZE, 800);
197 ::history (m_history, &m_history_event, H_SETUNIQUE, 1);
198 // Load history
199 HistorySaveLoad (false);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000200
201 // Set up mutex to make sure OutErr, OutWrite and RefreshPrompt do not interfere
202 // with each other when writing.
203
204 int error;
205 ::pthread_mutexattr_t attr;
206 error = ::pthread_mutexattr_init (&attr);
207 assert (error == 0);
208 error = ::pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
209 assert (error == 0);
210 error = ::pthread_mutex_init (&m_output_mutex, &attr);
211 assert (error == 0);
212 error = ::pthread_mutexattr_destroy (&attr);
213 assert (error == 0);
214
215 // Initialize time that ::el_gets was last called.
216
217 m_enter_elgets_time.tv_sec = 0;
218 m_enter_elgets_time.tv_usec = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000219}
220
221IOChannel::~IOChannel ()
222{
223 // Save history
224 HistorySaveLoad (true);
225
226 if (m_history != NULL)
227 {
228 ::history_end (m_history);
229 m_history = NULL;
230 }
231
232 if (m_edit_line != NULL)
233 {
234 ::el_end (m_edit_line);
235 m_edit_line = NULL;
236 }
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000237
238 ::pthread_mutex_destroy (&m_output_mutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000239}
240
241void
242IOChannel::HistorySaveLoad (bool save)
243{
244 if (m_history != NULL)
245 {
246 char history_path[PATH_MAX];
Johnny Chen23fd10c2010-08-27 22:35:26 +0000247 ::snprintf (history_path, sizeof(history_path), "~/.%s-history", SBHostOS::GetProgramFileSpec().GetFilename());
Greg Claytonc982c762010-07-09 20:39:50 +0000248 if ((size_t)SBFileSpec::ResolvePath (history_path, history_path, sizeof(history_path)) < sizeof(history_path) - 1)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000249 {
250 const char *path_ptr = history_path;
251 if (save)
252 ::history (m_history, &m_history_event, H_SAVE, path_ptr);
253 else
254 ::history (m_history, &m_history_event, H_LOAD, path_ptr);
255 }
256 }
257}
258
Caroline Tice969ed3d2011-05-02 20:41:46 +0000259void
260IOChannel::LibeditOutputBytesReceived (void *baton, const void *src, size_t src_len)
261{
262 // Make this a member variable.
263 // static std::string prompt_str;
264 IOChannel *io_channel = (IOChannel *) baton;
Caroline Tice86a73f92011-05-03 20:53:11 +0000265 IOLocker locker (io_channel->m_output_mutex);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000266 const char *bytes = (const char *) src;
267
268 if (io_channel->IsGettingCommand() && io_channel->m_expecting_prompt)
269 {
270 io_channel->m_prompt_str.append (bytes, src_len);
271 // Log this to make sure the prompt is really what you think it is.
272 if (io_channel->m_prompt_str.find (el_prompt(io_channel->m_edit_line)) == 0)
273 {
274 io_channel->m_expecting_prompt = false;
Caroline Tice86a73f92011-05-03 20:53:11 +0000275 io_channel->m_refresh_request_pending = false;
Caroline Tice969ed3d2011-05-02 20:41:46 +0000276 io_channel->OutWrite (io_channel->m_prompt_str.c_str(),
277 io_channel->m_prompt_str.size(), NO_ASYNC);
278 io_channel->m_prompt_str.clear();
279 }
Caroline Tice969ed3d2011-05-02 20:41:46 +0000280 }
281 else
282 {
283 if (io_channel->m_prompt_str.size() > 0)
284 io_channel->m_prompt_str.clear();
Caroline Tice86a73f92011-05-03 20:53:11 +0000285 std::string tmp_str (bytes, src_len);
286 if (tmp_str.find (el_prompt (io_channel->m_edit_line)) == 0)
287 io_channel->m_refresh_request_pending = false;
Caroline Tice969ed3d2011-05-02 20:41:46 +0000288 io_channel->OutWrite (bytes, src_len, NO_ASYNC);
289 }
290}
291
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000292bool
293IOChannel::LibeditGetInput (std::string &new_line)
294{
295 if (m_edit_line != NULL)
296 {
297 int line_len = 0;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000298
299 // Set boolean indicating whether or not el_gets is trying to get input (i.e. whether or not to attempt
300 // to refresh the prompt after writing data).
301 SetGettingCommand (true);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000302 m_expecting_prompt = true;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000303
304 // Call el_gets to prompt the user and read the user's input.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000305 const char *line = ::el_gets (m_edit_line, &line_len);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000306
307 // Re-set the boolean indicating whether or not el_gets is trying to get input.
308 SetGettingCommand (false);
309
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000310 if (line)
311 {
312 // strip any newlines off the end of the string...
313 while (line_len > 0 && (line[line_len - 1] == '\n' || line[line_len - 1] == '\r'))
314 --line_len;
315 if (line_len > 0)
316 {
317 ::history (m_history, &m_history_event, H_ENTER, line);
318 new_line.assign (line, line_len); // Omit the newline
319 }
320 else
321 {
322 // Someone just hit ENTER, return the empty string
323 new_line.clear();
324 }
325 // Return true to indicate success even if a string is empty
326 return true;
327 }
328 }
329 // Return false to indicate failure. This can happen when the file handle
330 // is closed (EOF).
331 new_line.clear();
332 return false;
333}
334
335void *
336IOChannel::IOReadThread (void *ptr)
337{
338 IOChannel *myself = static_cast<IOChannel *> (ptr);
339 myself->Run();
340 return NULL;
341}
342
343void
344IOChannel::Run ()
345{
346 SBListener listener("IOChannel::Run");
347 std::string new_line;
348
Greg Clayton66111032010-06-23 01:19:29 +0000349 SBBroadcaster interpreter_broadcaster (m_driver->GetDebugger().GetCommandInterpreter().GetBroadcaster());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000350 listener.StartListeningForEvents (interpreter_broadcaster,
351 SBCommandInterpreter::eBroadcastBitResetPrompt |
352 SBCommandInterpreter::eBroadcastBitThreadShouldExit |
Caroline Tice86a73f92011-05-03 20:53:11 +0000353 SBCommandInterpreter::eBroadcastBitQuitCommandReceived);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000354
355 listener.StartListeningForEvents (*this,
356 IOChannel::eBroadcastBitThreadShouldExit);
357
358 listener.StartListeningForEvents (*m_driver,
359 Driver::eBroadcastBitReadyForInput |
360 Driver::eBroadcastBitThreadShouldExit);
361
362 // Let anyone know that the IO channel is up and listening and ready for events
363 BroadcastEventByType (eBroadcastBitThreadDidStart);
364 bool done = false;
365 while (!done)
366 {
367 SBEvent event;
368
369 listener.WaitForEvent (UINT32_MAX, event);
370 if (!event.IsValid())
371 continue;
372
373 const uint32_t event_type = event.GetType();
374
375 if (event.GetBroadcaster().IsValid())
376 {
377 if (event.BroadcasterMatchesPtr (m_driver))
378 {
379 if (event_type & Driver::eBroadcastBitReadyForInput)
380 {
381 std::string line;
382
383 if (CommandQueueIsEmpty())
384 {
385 if (LibeditGetInput(line) == false)
386 {
387 // EOF or some other file error occurred
388 done = true;
389 continue;
390 }
391 }
392 else
393 {
394 GetCommandFromQueue (line);
395 }
396
397 // TO BE DONE: FIGURE OUT WHICH COMMANDS SHOULD NOT BE REPEATED IF USER PRESSES PLAIN 'RETURN'
398 // AND TAKE CARE OF THAT HERE.
399
400 SBEvent line_event(IOChannel::eBroadcastBitHasUserInput,
401 line.c_str(),
402 line.size());
403 BroadcastEvent (line_event);
404 }
405 else if (event_type & Driver::eBroadcastBitThreadShouldExit)
406 {
407 done = true;
408 break;
409 }
410 }
411 else if (event.BroadcasterMatchesRef (interpreter_broadcaster))
412 {
413 switch (event_type)
414 {
415 case SBCommandInterpreter::eBroadcastBitResetPrompt:
416 {
417 const char *new_prompt = SBEvent::GetCStringFromEvent (event);
418 if (new_prompt)
419 g_prompt_map[m_edit_line] = new_prompt;
420 }
421 break;
422
423 case SBCommandInterpreter::eBroadcastBitThreadShouldExit:
424 case SBCommandInterpreter::eBroadcastBitQuitCommandReceived:
425 done = true;
426 break;
427 }
428 }
429 else if (event.BroadcasterMatchesPtr (this))
430 {
431 if (event_type & IOChannel::eBroadcastBitThreadShouldExit)
432 {
433 done = true;
434 break;
435 }
436 }
437 }
438 }
439 BroadcastEventByType (IOChannel::eBroadcastBitThreadDidExit);
440 m_driver = NULL;
441 m_read_thread = NULL;
442}
443
444bool
445IOChannel::Start ()
446{
Greg Clayton2da6d492011-02-08 01:34:25 +0000447 if (IS_VALID_LLDB_HOST_THREAD(m_read_thread))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000448 return true;
449
450 m_read_thread = SBHostOS::ThreadCreate ("<lldb.driver.commandline_io>", IOChannel::IOReadThread, this,
451 NULL);
452
Greg Clayton2da6d492011-02-08 01:34:25 +0000453 return (IS_VALID_LLDB_HOST_THREAD(m_read_thread));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000454}
455
456bool
457IOChannel::Stop ()
458{
Greg Clayton2da6d492011-02-08 01:34:25 +0000459 if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000460 return true;
461
462 BroadcastEventByType (eBroadcastBitThreadShouldExit);
463
464 // Don't call Host::ThreadCancel since el_gets won't respond to this
465 // function call -- the thread will just die and all local variables in
466 // IOChannel::Run() won't get destructed down which is bad since there is
467 // a local listener holding onto broadcasters... To ensure proper shutdown,
468 // a ^D (control-D) sequence (0x04) should be written to other end of the
469 // the "in" file handle that was passed into the contructor as closing the
470 // file handle doesn't seem to make el_gets() exit....
471 return SBHostOS::ThreadJoin (m_read_thread, NULL, NULL);
472}
473
474void
475IOChannel::RefreshPrompt ()
476{
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000477 // If we are not in the middle of getting input from the user, there is no need to
478 // refresh the prompt.
Caroline Tice86a73f92011-05-03 20:53:11 +0000479 IOLocker locker (m_output_mutex);
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000480 if (! IsGettingCommand())
481 return;
482
Caroline Tice969ed3d2011-05-02 20:41:46 +0000483 // If we haven't finished writing the prompt, there's no need to refresh it.
484 if (m_expecting_prompt)
485 return;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000486
Caroline Tice86a73f92011-05-03 20:53:11 +0000487 if (m_refresh_request_pending)
488 return;
489
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000490 ::el_set (m_edit_line, EL_REFRESH);
Caroline Tice86a73f92011-05-03 20:53:11 +0000491 m_refresh_request_pending = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000492}
493
494void
Caroline Tice969ed3d2011-05-02 20:41:46 +0000495IOChannel::OutWrite (const char *buffer, size_t len, bool asynchronous)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000496{
497 if (len == 0)
498 return;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000499
Caroline Tice969ed3d2011-05-02 20:41:46 +0000500 // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
501 IOLocker locker (m_output_mutex);
Caroline Tice9088b062011-05-09 23:06:58 +0000502 if (m_driver->EditlineReaderIsTop() && asynchronous)
Caroline Ticefe1bdf22011-05-04 16:44:57 +0000503 ::fwrite (undo_prompt_string, 1, 4, m_out_file);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000504 ::fwrite (buffer, 1, len, m_out_file);
505 if (asynchronous)
506 m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000507}
508
509void
Caroline Tice969ed3d2011-05-02 20:41:46 +0000510IOChannel::ErrWrite (const char *buffer, size_t len, bool asynchronous)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000511{
512 if (len == 0)
513 return;
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000514
Caroline Tice969ed3d2011-05-02 20:41:46 +0000515 // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
516 IOLocker locker (m_output_mutex);
517 if (asynchronous)
Caroline Ticefe1bdf22011-05-04 16:44:57 +0000518 ::fwrite (undo_prompt_string, 1, 4, m_err_file);
Caroline Tice969ed3d2011-05-02 20:41:46 +0000519 ::fwrite (buffer, 1, len, m_err_file);
520 if (asynchronous)
521 m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000522}
523
524void
525IOChannel::AddCommandToQueue (const char *command)
526{
527 m_command_queue.push (std::string(command));
528}
529
530bool
531IOChannel::GetCommandFromQueue (std::string &cmd)
532{
533 if (m_command_queue.empty())
534 return false;
535 cmd.swap(m_command_queue.front());
536 m_command_queue.pop ();
537 return true;
538}
539
540int
541IOChannel::CommandQueueSize () const
542{
543 return m_command_queue.size();
544}
545
546void
547IOChannel::ClearCommandQueue ()
548{
549 while (!m_command_queue.empty())
550 m_command_queue.pop();
551}
552
553bool
554IOChannel::CommandQueueIsEmpty () const
555{
556 return m_command_queue.empty();
557}
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000558
559bool
560IOChannel::IsGettingCommand () const
561{
562 return m_getting_command;
563}
564
565void
566IOChannel::SetGettingCommand (bool new_value)
567{
568 m_getting_command = new_value;
569}
570
Caroline Ticebd13b8d2010-09-29 18:35:42 +0000571IOLocker::IOLocker (pthread_mutex_t &mutex) :
572 m_mutex_ptr (&mutex)
573{
574 if (m_mutex_ptr)
575 ::pthread_mutex_lock (m_mutex_ptr);
576
577}
578
579IOLocker::~IOLocker ()
580{
581 if (m_mutex_ptr)
582 ::pthread_mutex_unlock (m_mutex_ptr);
583}