Skip to content

Commit

Permalink
remove atomic array and replace reads/writes with a mutex. Fixes #27
Browse files Browse the repository at this point in the history
  • Loading branch information
Raffaello committed Apr 30, 2020
1 parent be5db37 commit 12ca16e
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 36 deletions.
2 changes: 1 addition & 1 deletion sdl2-vga-terminal/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ set(LIB_CONF ${LIB_NAME}-config)
set(LIB_VER ${LIB_CONF}-version)
if (MSVC)
# Requires VS 2015 Update 2 at least.
add_compile_definitions(_ENABLE_ATOMIC_ALIGNMENT_FIX)
#add_compile_definitions(_ENABLE_ATOMIC_ALIGNMENT_FIX)
endif()
include(CMakePackageConfigHelpers)

Expand Down
68 changes: 42 additions & 26 deletions sdl2-vga-terminal/src/VgaTerminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ VgaTerminal::VgaTerminal(const std::string &title, const int width, const int he

VgaTerminal::VgaTerminal(const std::string& title, const int x, const int y, const int width, const int height, const int winFlags, const int drvIndex, const int renFlags)
: Window(title, x, y, width, height, winFlags, drvIndex, renFlags),
_viewPortX(0), _viewPortY(0), mode(mode3)
mode(mode3), _viewPortX(0), _viewPortY(0)
{
//mode = mode3;
_viewPortWidth = mode.tw, _viewPortHeight = mode.th;
Expand All @@ -74,8 +74,7 @@ VgaTerminal::VgaTerminal(const std::string& title, const int x, const int y, con
_pal.colors[i].a = SDL_ALPHA_OPAQUE;
}

_pGrid = std::make_unique<std::atomic<_terminalChar_t>[]>(static_cast<uint64_t>(mode.tw) * mode.th);
//_pGrid = std::make_unique<_terminalChar_t[]>(static_cast<uint64_t>(mode.tw) * mode.th);
_pGrid = std::make_unique<_terminalChar_t[]>(static_cast<uint64_t>(mode.tw) * mode.th);

if ((SDL_WasInit(SDL_INIT_TIMER) == SDL_INIT_TIMER) && (SDL_WasInit(SDL_INIT_EVENTS) == SDL_INIT_EVENTS)) {
_cursorTimerId = SDL_AddTimer(cursor_time, _timerCallBackWrapper, this);
Expand Down Expand Up @@ -173,8 +172,10 @@ void VgaTerminal::write(const uint8_t c, const uint8_t col, const uint8_t bgCol)
int pos = _curX + _curY * mode.tw;
_terminalChar_t tc;
tc.bgCol = bgCol, tc.c = c, tc.col = col, tc.rendered = false;
_pGrid[pos] = tc;

{
std::lock_guard lck(_pGridMutex);
_pGrid[pos] = tc;
}
_incrementCursorPosition();
}

Expand All @@ -199,13 +200,17 @@ void VgaTerminal::writeXY(const uint8_t x, const uint8_t y, const std::string &s
* @param y
* @return VgaTerminal::terminalChar_t defaultNullChar if out of screen
*/
VgaTerminal::terminalChar_t VgaTerminal::at(const uint8_t x, const uint8_t y) const noexcept
VgaTerminal::terminalChar_t VgaTerminal::at(const uint8_t x, const uint8_t y) noexcept
{
if (x >= _viewPortWidth || y >= _viewPortHeight) {
return _defaultNullChar;
}

_terminalChar_t _tc = _pGrid[(static_cast<size_t>(y) + _viewPortY) * mode.tw + x + _viewPortX];

_terminalChar_t _tc;
{
std::lock_guard lck(_pGridMutex);
_tc = _pGrid[(static_cast<size_t>(y) + _viewPortY) * mode.tw + x + _viewPortX];
}
terminalChar_t tc;
tc.c = _tc.c,
tc.col = _tc.col,
Expand All @@ -226,7 +231,11 @@ void VgaTerminal::_renderGridPartialY(const uint8_t y1, const uint8_t y2, const
void VgaTerminal::_renderGridLinePartialX(const uint8_t x1, const uint8_t x2, const int yw, const int ych, const bool force)
{
for (int i = x1, i2 = yw + x1; i < x2; i++, i2++) {
_terminalChar_t tc = _pGrid[i2];
_terminalChar_t tc;
{
std::lock_guard lck(_pGridMutex);
tc = _pGrid[i2];
}
if (!force && tc.rendered) {
continue;
}
Expand All @@ -248,7 +257,11 @@ void VgaTerminal::render(const bool force)
int yw = curY * mode.tw;
int ych = curY * mode.ch;
int icur = static_cast<int>(curY) * mode.tw + curX;
_terminalChar_t tc = _pGrid[icur];
_terminalChar_t tc;
{
std::lock_guard lck(_pGridMutex);
tc = _pGrid[icur];
}
SDL_Point p = { curX * mode.cw, ych };

// top cursor grid
Expand All @@ -275,10 +288,13 @@ void VgaTerminal::clear() noexcept
const int vy = _viewPortY + _viewPortHeight;
const int vx = _viewPortX + _viewPortWidth;

for (int j = _viewPortY; j < vy; j++) {
int j2 = j * mode.tw;
for (int i = _viewPortX; i < vx; i++) {
_pGrid[static_cast<size_t>(i) + j2] = _defaultNullChar;
{
std::lock_guard lck(_pGridMutex);
for (int j = _viewPortY; j < vy; j++) {
int j2 = j * mode.tw;
for (int i = _viewPortX; i < vx; i++) {
_pGrid[static_cast<size_t>(i) + j2] = _defaultNullChar;
}
}
}

Expand Down Expand Up @@ -394,9 +410,10 @@ void VgaTerminal::_busy() noexcept
_onIdle = false;
// TODO these 4 lines below should be promoted to a method and reused also in the timer routine
int icur = _curY * mode.tw + _curX;
_terminalChar_t tc = _pGrid[icur];
tc.rendered = false;
_pGrid[icur] = tc;
{
std::lock_guard lck(_pGridMutex);
_pGrid[icur].rendered = false;
}
}

uint32_t VgaTerminal::_timerCallBackWrapper(uint32_t interval, void* param)
Expand All @@ -420,9 +437,10 @@ uint32_t VgaTerminal::_timerCallBack(uint32_t interval)
}
// TODO wrap in a cursor function these ops: icur and set rendered flag to false, or in 2
int icur = _curY * mode.tw + _curX;
_terminalChar_t tc = _pGrid[icur];
tc.rendered = false;
_pGrid[icur] = tc;
{
std::lock_guard lck(_pGridMutex);
_pGrid[icur].rendered = false;
}

interval = cursor_time;

Expand Down Expand Up @@ -462,6 +480,7 @@ void VgaTerminal::_scrollDownGrid() noexcept
auto vh = _viewPortY + _viewPortHeight;
auto vw = _viewPortWidth + _viewPortWidth;

std::lock_guard lck(_pGridMutex);
for (int j = _viewPortY + 1; j < vh ; j++)
{
int j2 = j * mode.tw;
Expand All @@ -471,16 +490,13 @@ void VgaTerminal::_scrollDownGrid() noexcept
{
int i2 = i + j2;
int ii2 = i + jj2;
_terminalChar_t tc1 = _pGrid[i2];
_terminalChar_t tc2 = _pGrid[ii2];

if (tc1.rendered && tc1 == tc2) {
if (_pGrid[i2].rendered && _pGrid[i2] == _pGrid[ii2]) {
continue;
}

tc2 = tc1;
tc2.rendered = false;
_pGrid[ii2] = tc2;
_pGrid[ii2] = _pGrid[i2];
_pGrid[ii2].rendered = false;
}
}

Expand Down
18 changes: 9 additions & 9 deletions sdl2-vga-terminal/src/VgaTerminal.hpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#pragma once

#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_FULL_VER < 190023918)
# error "Visual Studio 2015 Update 2 at least is required"
#endif
//#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_FULL_VER < 190023918)
//# error "Visual Studio 2015 Update 2 at least is required"
//#endif

#include "Window.hpp"
#include <memory>
#include <string>
#include <bitset>
#include <atomic>
#include <mutex>


class VgaTerminal : public Window
Expand Down Expand Up @@ -63,7 +64,7 @@ class VgaTerminal : public Window
void write(const uint8_t c, const uint8_t col, const uint8_t bgCol) noexcept;
void write(const std::string &str, const uint8_t col, const uint8_t bgCol) noexcept;
void writeXY(const uint8_t x, const uint8_t y, const std::string &str, const uint8_t col, const uint8_t bgCol) noexcept;
terminalChar_t at(const uint8_t x, const uint8_t y) const noexcept;
terminalChar_t at(const uint8_t x, const uint8_t y) noexcept;

void render(const bool force = false);
void clear() noexcept;
Expand Down Expand Up @@ -99,11 +100,11 @@ class VgaTerminal : public Window
static const videoMode_t mode3;
std::unique_ptr<SDL_Color[]> pCol;
SDL_Palette _pal;
// TODO potentially candidate for atomic, when setMode is available
// at the moment is like a const, so defined as const...
// potentially candidate for atomic, when setMode is available
// at the moment is like a const, so defined as const...
const videoMode_t mode;
std::unique_ptr<std::atomic<_terminalChar_t>[]> _pGrid;
//std::unique_ptr<_terminalChar_t[]> _pGrid;
std::unique_ptr<_terminalChar_t[]> _pGrid;
std::mutex _pGridMutex;
const _terminalChar_t _defaultNullChar = _terminalChar_t({ 0, 0, 0, false });

std::atomic<uint8_t> _curX = 0;
Expand All @@ -115,7 +116,6 @@ class VgaTerminal : public Window

std::atomic<bool> _drawCursor = true;
SDL_TimerID _cursorTimerId = 0;
//std::mutex _cursortTimerMutex;
std::atomic<bool> _onIdle = true;
// TODO: find a better name for the method.
void _busy() noexcept;
Expand Down

0 comments on commit 12ca16e

Please sign in to comment.