Просмотр исходного кода

logging thread

feature/dependency-graph
Martin Dørum 5 лет назад
Родитель
Сommit
1125d2f2b6
6 измененных файлов: 91 добавлений и 10 удалений
  1. 2
    2
      Makefile
  2. 2
    1
      src/SourceFile.cc
  3. 54
    0
      src/logger.cc
  4. 15
    0
      src/logger.h
  5. 5
    2
      src/main.cc
  6. 13
    5
      src/sys.cc

+ 2
- 2
Makefile Просмотреть файл

SRCS = \ SRCS = \
src/BBBParser.cc src/SourceFile.cc src/toolchain.cc src/globals.cc \ src/BBBParser.cc src/SourceFile.cc src/toolchain.cc src/globals.cc \
src/sys.cc src/parallel.cc src/main.cc
src/logger.cc src/sys.cc src/parallel.cc src/main.cc
HDRS = src/BBBParser.h src/SourceFile.h src/toolchain.h src/globals.h \ HDRS = src/BBBParser.h src/SourceFile.h src/toolchain.h src/globals.h \
src/sys.h src/parallel.h
src/logger.h src/sys.h src/parallel.h
BUILD = build BUILD = build
OBJS = $(patsubst %,$(BUILD)/%.o,$(SRCS)) OBJS = $(patsubst %,$(BUILD)/%.o,$(SRCS))
CFLAGS = -g -Wall -Wextra -Wno-unused-parameter CFLAGS = -g -Wall -Wextra -Wno-unused-parameter

+ 2
- 1
src/SourceFile.cc Просмотреть файл

#include <string.h> #include <string.h>


#include "toolchain.h" #include "toolchain.h"
#include "logger.h"


static bool startsWith(BBBParser &parser, const char *str) { static bool startsWith(BBBParser &parser, const char *str) {
for (size_t i = 0; str[i] != '\0'; ++i) { for (size_t i = 0; str[i] != '\0'; ++i) {
void SourceFile::compile(const std::string &outDir) const { void SourceFile::compile(const std::string &outDir) const {
// TODO: Send this as a message to some printer thread instead, // TODO: Send this as a message to some printer thread instead,
// because this happens in multiple threads // because this happens in multiple threads
std::cerr << "Compile " << objectPath(outDir) << '\n';
logger::log("Compile " + objectPath(outDir));
toolchain::compile(compileFlags(), type_, dir_, name_, outDir); toolchain::compile(compileFlags(), type_, dir_, name_, outDir);


// Nothing will need compile flags after it's compiled, so no reason to // Nothing will need compile flags after it's compiled, so no reason to

+ 54
- 0
src/logger.cc Просмотреть файл

#include "logger.h"

#include <mutex>
#include <vector>
#include <condition_variable>
#include <thread>
#include <iostream>
#include <atomic>

namespace logger {

static std::vector<std::string> queue;
static std::mutex mut;
static std::condition_variable cond;
static std::thread thread;
static std::atomic_bool running;

static void print(const std::string &msg) {
std::cerr << msg << '\n';
}

LogContext::~LogContext() {
running.store(false);
cond.notify_one();
thread.join();
}

void log(std::string msg) {
std::unique_lock<std::mutex> lock(mut);
queue.emplace_back(std::move(msg));
lock.unlock();
cond.notify_one();
}

LogContext init() {
running = true;

thread = std::thread([&] {
std::unique_lock<std::mutex> lock(mut);
while (running.load()) {
cond.wait(lock, [&] { return !queue.empty() || !running.load(); });

for (std::string &msg: queue) {
print(msg);
}

queue.clear();
}
});

return LogContext{};
}

}

+ 15
- 0
src/logger.h Просмотреть файл

#pragma once

#include <string>

namespace logger {

struct LogContext {
~LogContext();
};

void log(std::string msg);

LogContext init();

}

+ 5
- 2
src/main.cc Просмотреть файл

#include "parallel.h" #include "parallel.h"
#include "toolchain.h" #include "toolchain.h"
#include "globals.h" #include "globals.h"
#include "logger.h"


static void readDir(std::string dir, std::vector<SourceFile> &sources, static void readDir(std::string dir, std::vector<SourceFile> &sources,
BBBParser::Variables vars); BBBParser::Variables vars);
const std::vector<SourceFile> &sources, const std::vector<SourceFile> &sources,
const std::string &outDir, const std::string &name, const std::string &outDir, const std::string &name,
toolchain::TargetType targetType) { toolchain::TargetType targetType) {
std::cerr << "Link " << outDir << '/' << name << '\n';
logger::log("Link " + outDir + '/' + name);


std::vector<std::string> ldFlags; std::vector<std::string> ldFlags;
std::unordered_set<std::string> ldFlagsSet; std::unordered_set<std::string> ldFlagsSet;
} }


int main(int argc, char **argv) { int main(int argc, char **argv) {
logger::LogContext logCtx = logger::init();

std::vector<std::string> srcDirs; std::vector<std::string> srcDirs;
std::string outDir = "bbbuild"; std::string outDir = "bbbuild";
int jobs = parallel::coreCount(); int jobs = parallel::coreCount();
case Action::BUILD: case Action::BUILD:
// TODO: Support more types than BINARY // TODO: Support more types than BINARY
if (!compileAndLink(sources, outDir, jobs, target, toolchain::TargetType::BINARY)) { if (!compileAndLink(sources, outDir, jobs, target, toolchain::TargetType::BINARY)) {
std::cerr << "Nothing to do.\n";
logger::log("Nothing to do.\n");
} }
break; break;



+ 13
- 5
src/sys.cc Просмотреть файл

#include <stdexcept> #include <stdexcept>


#include "globals.h" #include "globals.h"
#include "logger.h"


namespace sys { namespace sys {




void execute(std::vector<const char *> &args, std::string *output) { void execute(std::vector<const char *> &args, std::string *output) {
if (global::verbose) { if (global::verbose) {
std::string str;
for (size_t i = 0; i < args.size(); ++i) { for (size_t i = 0; i < args.size(); ++i) {
if (i == 0) { if (i == 0) {
fprintf(stderr, " %s", args[i]);
str += " ";
} else { } else {
fprintf(stderr, " %s", args[i]);
str += " ";
} }
str += args[i];
} }
fprintf(stderr, "\n");
logger::log(str);
} }


// argv[0] should be interpreted as a shell command, because being able to run // argv[0] should be interpreted as a shell command, because being able to run
perror(argv[0]); perror(argv[0]);
abort(); abort();
} }

// This shouldn't happen
exit(0);
} else if (child < 0) { } else if (child < 0) {
throw std::runtime_error(std::string("fork: ") + strerror(errno)); throw std::runtime_error(std::string("fork: ") + strerror(errno));
} }
ssize_t num = read(fds[0], buf, sizeof(buf) - 1); ssize_t num = read(fds[0], buf, sizeof(buf) - 1);
if (num < 0 && errno != EAGAIN) { if (num < 0 && errno != EAGAIN) {
close(fds[0]); close(fds[0]);
throw std::runtime_error(std::string("read: ") + strerror(errno));
throw std::runtime_error(
std::string("read: ") + strerror(errno) +
" (fd: " + std::to_string(fds[0]) + ")");
} else if (num < 0) { } else if (num < 0) {
continue; continue;
} }


if (num == 0) { if (num == 0) {
close(fds[1]);
close(fds[0]);
break; break;
} }



Загрузка…
Отмена
Сохранить