diff --git a/Makefile b/Makefile index 43226dc..c605a02 100644 --- a/Makefile +++ b/Makefile @@ -67,6 +67,9 @@ NAMES_C=$(SOURCES_C:.c=) PROGRAMS_C=$(addprefix $(BIN)/, $(NAMES_C)) SOURCES_CXX=\ +ch01/alarm_cpp.cpp \ +ch01/alarm_fork_cpp.cpp \ +ch01/alarm_thread_cpp.cpp \ ch03/alarm_mutex_cpp.cpp \ ch04/pipe_cpp.cpp @@ -77,7 +80,7 @@ all: format dirs ${PROGRAMS_C} ${PROGRAMS_CXX} format: #clang-format -i $(SOURCE)/*.c* - #clang-format -i $(SOURCE)/*.h* + clang-format -i $(SOURCE)/*.h* clang-format -i $(SOURCE)/*/*.c* clang-format -i $(SOURCE)/*/*.h* diff --git a/src/ch01/alarm_cpp.cpp b/src/ch01/alarm_cpp.cpp new file mode 100644 index 0000000..54eda7c --- /dev/null +++ b/src/ch01/alarm_cpp.cpp @@ -0,0 +1,38 @@ + +#include +#include +#include +#include +#include + +int +main(int argc, char* argv[]) +{ + std::string line; + std::string message; + + while (true) { + std::cout << "Alarm> "; + + std::getline(std::cin, line); + if (!std::cin.good()) + exit(0); + + if (line.empty()) + continue; + + std::istringstream in(line); + + unsigned seconds = -1; + in >> seconds; + message = in.str(); + + if (seconds < 1 || message.empty()) { + std::cout << "Bad command\n"; + continue; + } + + std::this_thread::sleep_for(std::chrono::seconds(seconds)); + std::cout << message << "\n"; + } +} diff --git a/src/ch01/alarm_fork_cpp.cpp b/src/ch01/alarm_fork_cpp.cpp new file mode 100644 index 0000000..746e6e8 --- /dev/null +++ b/src/ch01/alarm_fork_cpp.cpp @@ -0,0 +1,57 @@ + +#include "errors.hpp" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +int +main(int argc, char* argv[]) +{ + std::string line; + std::string message; + + while (true) { + std::cout << "Alarm> "; + + std::getline(std::cin, line); + if (!std::cin.good()) + exit(0); + + if (line.empty()) + continue; + + std::istringstream in(line); + + unsigned seconds = -1; + in >> seconds; + message = in.str(); + + if (seconds < 1 || message.empty()) { + std::cout << "Bad command\n"; + continue; + } + + pid_t pid = fork(); + if (pid == (pid_t) -1) + errno_abort("Fork"); + if (pid == (pid_t) 0) { + std::this_thread::sleep_for(std::chrono::seconds(seconds)); + std::cout << message << "\n"; + std::exit(0); + } + + do { + pid = waitpid((pid_t) -1, NULL, WNOHANG); + if (pid == (pid_t) -1) + errno_abort("Wait for child"); + } while (pid != (pid_t) 0); + } +} diff --git a/src/ch01/alarm_thread.c b/src/ch01/alarm_thread.c index b09e483..cda96e7 100644 --- a/src/ch01/alarm_thread.c +++ b/src/ch01/alarm_thread.c @@ -26,6 +26,7 @@ alarm_thread(void* arg) free(alarm); return NULL; } + int main(int argc, char* argv[]) { diff --git a/src/ch01/alarm_thread_cpp.cpp b/src/ch01/alarm_thread_cpp.cpp new file mode 100644 index 0000000..c7551cc --- /dev/null +++ b/src/ch01/alarm_thread_cpp.cpp @@ -0,0 +1,52 @@ + +#include +#include +#include +#include +#include +#include + +struct Alarm { + unsigned seconds = -1; + std::string message; +}; + +using AlarmPtr = std::unique_ptr; + +void +alarmHandler(AlarmPtr alarm) +{ + std::this_thread::sleep_for(std::chrono::seconds(alarm->seconds)); + std::cout << alarm->message << "\n"; +} + +int +main(int argc, char* argv[]) +{ + std::string line; + + while (true) { + std::cout << "Alarm> "; + + std::getline(std::cin, line); + if (!std::cin.good()) + exit(0); + + if (line.empty()) + continue; + + std::stringstream in(line); + + AlarmPtr alarm(new Alarm()); + in >> alarm->seconds; + alarm->message = in.str(); + + if (alarm->seconds < 1 || alarm->message.empty()) { + std::cout << "Bad command\n"; + continue; + } + + std::thread t(alarmHandler, std::move(alarm)); + t.detach(); + } +} diff --git a/src/errors.h b/src/errors.h index c9c1c3a..1637749 100644 --- a/src/errors.h +++ b/src/errors.h @@ -1,11 +1,11 @@ #ifndef __errors_h #define __errors_h -#include #include #include #include #include +#include /* * Define a macro that can be used for diagnostic output from @@ -14,9 +14,9 @@ * expands to nothing. */ #ifdef DEBUG -# define DPRINTF(arg) printf arg +#define DPRINTF(arg) printf arg #else -# define DPRINTF(arg) +#define DPRINTF(arg) #endif /* @@ -35,15 +35,25 @@ * a ";" following the ")" in the do...while construct, err_abort and * errno_abort can be used as if they were function calls. */ -#define err_abort(code,text) do { \ - fprintf (stderr, "%s at \"%s\":%d: %s\n", \ - text, __FILE__, __LINE__, strerror (code)); \ - abort (); \ - } while (0) -#define errno_abort(text) do { \ - fprintf (stderr, "%s at \"%s\":%d: %s\n", \ - text, __FILE__, __LINE__, strerror (errno)); \ - abort (); \ - } while (0) +#define err_abort(code, text) \ + do { \ + fprintf(stderr, \ + "%s at \"%s\":%d: %s\n", \ + text, \ + __FILE__, \ + __LINE__, \ + strerror(code)); \ + abort(); \ + } while (0) +#define errno_abort(text) \ + do { \ + fprintf(stderr, \ + "%s at \"%s\":%d: %s\n", \ + text, \ + __FILE__, \ + __LINE__, \ + strerror(errno)); \ + abort(); \ + } while (0) #endif diff --git a/src/errors.hpp b/src/errors.hpp new file mode 100644 index 0000000..0e39c4d --- /dev/null +++ b/src/errors.hpp @@ -0,0 +1,21 @@ + +#ifndef SRC_ERRORS_HPP_ +#define SRC_ERRORS_HPP_ + +#include +#include + +#define err_abort(code, text) \ + do { \ + std::cerr << text << " at \"" << __FILE__ << ":" << __LINE__ \ + << ": error no:" << code << std::endl; \ + std::terminate(); \ + } while (false) + +#define errno_abort(text) \ + do { \ + std::cerr << text << " at \"" << __FILE__ << ":" << __LINE__ << std::endl; \ + std::terminate(); \ + } while (false) + +#endif // SRC_ERRORS_HPP_