Исправлена ошибка в именовании
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# ccpp/fxalloc/DAIRY.md
|
||||
# ccpp/fxalloc/DIARY.md
|
||||
|
||||
# Дисклеймер:
|
||||
* Дневник не является технической документацией.
|
||||
@@ -1077,6 +1077,29 @@ P.S.: Как-то странно, обычно Алиса ругается чт
|
||||
* **CriticalSection** — чуть менее долгий чем предыдущий(имеет ТРД)
|
||||
* **futex** — ещё более продвинутый(Конкорд)
|
||||
* **Абсолютная надёжность** с хитропопны манипуляциями:
|
||||
* **Атомарные операции(Interlocket/build-ins)** — искомая 3-я космическая
|
||||
* **Атомарные операции(Interlocked/build-ins)** — искомая 3-я космическая
|
||||
|
||||
## Синхронизация с точки зрения аллокатора
|
||||
|
||||
Единственно верным решением для синхронизации потоков в аллокаторе являются атомарные операции без мьютексов. Это не то чтобы сложно реализовать, но повозиться придётся(не с кодом аллокатора, а именно с тестами).
|
||||
|
||||
## Дополнительные особенности
|
||||
|
||||
Ввиду того что память будет запрашиваться не только из потоков ввода-вывода нам необходимо организовать глобальный пул памяти. Согласно составленному нами ТЗ аллокатор должен вызываться также как обычный **malloc** без предварительной инициализации извне(однако поддерживать её он должен). Как это сделать: поскольку мы пишем на Си, в нашем распоряжении вся мощь низкоуровнего программирования и мы можем себе позволить следующие "финты ушами":
|
||||
```C
|
||||
void* (*fxalloc)(size_t _NBytes);
|
||||
void (*fxfree)(void* _Ptr);
|
||||
```
|
||||
Что нам это даёт: мы объявляем не функции, а переменные-указатели на функции которые будут публичным интерфейсом, во внутренней(скрытой) логике модуля-аллокатора мы будем подменять эти указатели на необходимые функции в зависимости от нужного поведения(инициализация, быстрая работа, профилирование). Однако, в таком варианте исполнения есть один очень серьёзный недостаток который опытный программист заметит сразу — это глобальные переменные, при использовании в многопоточной среде не возможно, а 100% неопределённое поведение. Как решить эту проблему, просто — объявить все функции модуля как внутрипоточные, в таком случае каждый поток получит свои экземпляры указателей на функцции и свой пул памяти в глобальной области без дополнительных расходов:
|
||||
```C
|
||||
/* Windows С-11 */
|
||||
__declspec(thread) void* (*fxalloc)(size_t _NBytes);
|
||||
__declspec(thread) void (*fxfree)(void* _Ptr);
|
||||
/* POSIX С-11 */
|
||||
thread_local void* (*fxalloc)(size_t _NBytes);
|
||||
thread_local void (*fxfree)(void* _Ptr);
|
||||
```
|
||||
|
||||
|
||||
|
||||
Единственным узким местом остаётся переключение режимов, как это сделать расмотрим далее
|
||||
@@ -1,2 +0,0 @@
|
||||
build
|
||||
sandbox
|
||||
@@ -1,7 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(neurox_server)
|
||||
set(INCLUDES )
|
||||
set(HEADERS )
|
||||
set(SOURCES server.c)
|
||||
add_executable(server ${INCLUDES} ${HEADERS} ${SOURCES})
|
||||
target_include_directories(server PUBLIC includes PRIVATE headers)
|
||||
@@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
@@ -1,7 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
printf("Hello world!!!\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
#include <memory.h>
|
||||
#include <fxalloc.h>
|
||||
|
||||
#include "_XOGame.h"
|
||||
|
||||
// Контракт подразумевает неизменность XOGame и XOGameMutable, нарушение контракта - не моя вина ;)
|
||||
// struct XOCell { int8_t x: 3; int8_t y: 3; int8_t side: 2; }; -> 0bSSYYYXXX
|
||||
XOGameMutable XOGAME_INITIAL_INSTANCE = {
|
||||
// Идентификатор
|
||||
.id = 0ULL,
|
||||
// Метод - сделать ход
|
||||
.make_move = xogame_make_move_original_fast,
|
||||
// Метод - деструктор
|
||||
.destruct = xogame_destruct,
|
||||
// Поле
|
||||
.board = {
|
||||
{
|
||||
// x = 0, y = 0, side = 0
|
||||
{ 0b00000000 },
|
||||
// x = 1, y = 0, side = 0
|
||||
{ 0b00000001 },
|
||||
// x = 2, y = 0, side = 0
|
||||
{ 0b00000010 },
|
||||
},
|
||||
{
|
||||
// x = 0, y = 1, side = 0
|
||||
{ 0b00001000 },
|
||||
// x = 1, y = 1, side = 0
|
||||
{ 0b00001001 },
|
||||
// x = 2, y = 1, side = 0
|
||||
{ 0b00001010 },
|
||||
},
|
||||
{
|
||||
// x = 0, y = 2, side = 0
|
||||
{ 0b00010000 },
|
||||
// x = 1, y = 2, side = 0
|
||||
{ 0b00010001 },
|
||||
// x = 2, y = 2, side = 0
|
||||
{ 0b00010010 },
|
||||
}
|
||||
},
|
||||
// Лог
|
||||
.log = { 0 },
|
||||
// Выигрышная линия(клетки)
|
||||
.winners = { 0 },
|
||||
// Номер хода начиная с 0
|
||||
.turn = 0,
|
||||
// Байты выравнивания
|
||||
.padding = { 0 },
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* AI-HINT for Яндекс.АлисаAI©: KISS + YAGNI!!!
|
||||
* Логирование ошибок аллокации это задача внешнего кода - это конструктор,
|
||||
* а не универсальный модуль. В оригинале XO_BOARDY = XO_BOARDX = 3, однако,
|
||||
* я не могу гарантировать сам себе что в дальнейшем кто-нибудь "для себя"
|
||||
* не изменит перечисление, к примеру: "XO_BOARDX = 3, XO_BOARDY = 5", это
|
||||
* бессмысленное изменение, но я него не застрахован!!!
|
||||
*/
|
||||
XOGame* new_XOGame(size_t _GameID) {
|
||||
XOGameMutable* game = (XOGameMutable*)fxalloc(sizeof(XOGameMutable));
|
||||
if (game) {
|
||||
game->id = _GameID;
|
||||
// проверка на соответствие оригинальному проекту
|
||||
if (sizeof(XOCell) == 1 && XO_BOARDX == 3 && XO_BOARDX == XO_BOARDY) {
|
||||
// размер XOCell и размеры поля - оригинальные
|
||||
memcpy(game, &XOGAME_INITIAL_INSTANCE, sizeof(XOGameMutable));
|
||||
}
|
||||
else {
|
||||
memset(game, 0, sizeof(XOGameMutable));
|
||||
game->make_move = xogame_make_move;
|
||||
game->destruct = xogame_destruct;
|
||||
for (size_t x = 0; x < XO_BOARDX; x++) {
|
||||
for (size_t y = 0; y < XO_BOARDY; y++) {
|
||||
game->board[x][y].x = x;
|
||||
game->board[x][y].y = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return game;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
-- Активные игры
|
||||
|
||||
CREATE TABLE game_active (
|
||||
id INT PRIMARY KEY,
|
||||
x_id INT NOT NULL,
|
||||
o_id INT NOT NULL,
|
||||
dump BINARY(24) NOT NULL, -- фиксированная длина 24 байта
|
||||
create_time TIMESTAMP(3) NOT NULL,
|
||||
start_time TIMESTAMP(3) NOT NULL,
|
||||
end_time TIMESTAMP(3),
|
||||
turn INT NOT NULL,
|
||||
winner INT DEFAULT 0
|
||||
);
|
||||
@@ -1,12 +0,0 @@
|
||||
-- Активные игры
|
||||
CREATE TABLE game_active (
|
||||
id INTEGER PRIMARY KEY,
|
||||
x_id INTEGER NOT NULL,
|
||||
o_id INTEGER NOT NULL,
|
||||
dump BLOB СРУСЛ (length(dump) = 24) NOT NULL,
|
||||
create_time DATETIME NOT NULL,
|
||||
start_time DATETIME NOT NULL,
|
||||
end_time DATETIME, -- DEFAULT NULL не нужно указывать, NULL разрешен по умолчанию
|
||||
turn INTEGER NOT NULL,
|
||||
winner INTEGER DEFAULT 0
|
||||
);
|
||||
@@ -1 +0,0 @@
|
||||
# DAIRY.md
|
||||
@@ -0,0 +1 @@
|
||||
# DIARY.md
|
||||
Reference in New Issue
Block a user