Add ch01 C++ threading equivalents

This commit is contained in:
Bassem Girgis
2018-10-18 14:47:36 -05:00
parent c8a8949366
commit 7b46aaf5f9
7 changed files with 196 additions and 14 deletions

View File

@@ -67,6 +67,9 @@ NAMES_C=$(SOURCES_C:.c=)
PROGRAMS_C=$(addprefix $(BIN)/, $(NAMES_C)) PROGRAMS_C=$(addprefix $(BIN)/, $(NAMES_C))
SOURCES_CXX=\ SOURCES_CXX=\
ch01/alarm_cpp.cpp \
ch01/alarm_fork_cpp.cpp \
ch01/alarm_thread_cpp.cpp \
ch03/alarm_mutex_cpp.cpp \ ch03/alarm_mutex_cpp.cpp \
ch04/pipe_cpp.cpp ch04/pipe_cpp.cpp
@@ -77,7 +80,7 @@ all: format dirs ${PROGRAMS_C} ${PROGRAMS_CXX}
format: format:
#clang-format -i $(SOURCE)/*.c* #clang-format -i $(SOURCE)/*.c*
#clang-format -i $(SOURCE)/*.h* clang-format -i $(SOURCE)/*.h*
clang-format -i $(SOURCE)/*/*.c* clang-format -i $(SOURCE)/*/*.c*
clang-format -i $(SOURCE)/*/*.h* clang-format -i $(SOURCE)/*/*.h*

38
src/ch01/alarm_cpp.cpp Normal file
View File

@@ -0,0 +1,38 @@
#include <chrono>
#include <iostream>
#include <sstream>
#include <string>
#include <thread>
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";
}
}

View File

@@ -0,0 +1,57 @@
#include "errors.hpp"
#include <chrono>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <thread>
#include <sys/types.h>
#include <unistd.h>
#include <wait.h>
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);
}
}

View File

@@ -26,6 +26,7 @@ alarm_thread(void* arg)
free(alarm); free(alarm);
return NULL; return NULL;
} }
int int
main(int argc, char* argv[]) main(int argc, char* argv[])
{ {

View File

@@ -0,0 +1,52 @@
#include <chrono>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <thread>
struct Alarm {
unsigned seconds = -1;
std::string message;
};
using AlarmPtr = std::unique_ptr<Alarm>;
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();
}
}

View File

@@ -1,11 +1,11 @@
#ifndef __errors_h #ifndef __errors_h
#define __errors_h #define __errors_h
#include <unistd.h>
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
/* /*
* Define a macro that can be used for diagnostic output from * Define a macro that can be used for diagnostic output from
@@ -14,9 +14,9 @@
* expands to nothing. * expands to nothing.
*/ */
#ifdef DEBUG #ifdef DEBUG
# define DPRINTF(arg) printf arg #define DPRINTF(arg) printf arg
#else #else
# define DPRINTF(arg) #define DPRINTF(arg)
#endif #endif
/* /*
@@ -35,15 +35,25 @@
* a ";" following the ")" in the do...while construct, err_abort and * a ";" following the ")" in the do...while construct, err_abort and
* errno_abort can be used as if they were function calls. * errno_abort can be used as if they were function calls.
*/ */
#define err_abort(code,text) do { \ #define err_abort(code, text) \
fprintf (stderr, "%s at \"%s\":%d: %s\n", \ do { \
text, __FILE__, __LINE__, strerror (code)); \ fprintf(stderr, \
abort (); \ "%s at \"%s\":%d: %s\n", \
text, \
__FILE__, \
__LINE__, \
strerror(code)); \
abort(); \
} while (0) } while (0)
#define errno_abort(text) do { \ #define errno_abort(text) \
fprintf (stderr, "%s at \"%s\":%d: %s\n", \ do { \
text, __FILE__, __LINE__, strerror (errno)); \ fprintf(stderr, \
abort (); \ "%s at \"%s\":%d: %s\n", \
text, \
__FILE__, \
__LINE__, \
strerror(errno)); \
abort(); \
} while (0) } while (0)
#endif #endif

21
src/errors.hpp Normal file
View File

@@ -0,0 +1,21 @@
#ifndef SRC_ERRORS_HPP_
#define SRC_ERRORS_HPP_
#include <exception>
#include <iostream>
#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_