Skip to content

Commit

Permalink
Introduce src/compat/ for all bins
Browse files Browse the repository at this point in the history
I've created the new files src/compat/compat.{hc}. These
are available to all binaries by adding src to the include
directories, and src/compat/compat.c to the sources. Several
functions are implemented here which one or more target
operating systems are missing, right now all related to time.
This includes clock_nanosleep(), which is missing on OS X and
DragonFly BSD. Eliminate the other three definitions of
timespec_to_ns() and friends. Standardize on NANOSECS_IN_SEC
rather than the more opaque GIG. Progress on #1121.
  • Loading branch information
dankamongmen committed Jan 10, 2021
1 parent e7d0b18 commit 8283adc
Show file tree
Hide file tree
Showing 15 changed files with 99 additions and 71 deletions.
11 changes: 9 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,11 @@ set_property(GLOBAL APPEND PROPERTY PACKAGES_FOUND qrcodegen)
endif()
find_library(LIBRT rt)

file(GLOB COMPATSRC CONFIGURE_DEPENDS src/compat/compat.c)

# libnotcurses (core shared library, core static library)
file(GLOB NCSRCS CONFIGURE_DEPENDS src/lib/*.c src/lib/*.cpp)
add_library(notcurses SHARED ${NCSRCS})
add_library(notcurses SHARED ${NCSRCS} ${COMPATSRC})
if(${USE_STATIC})
add_library(notcurses-static STATIC ${NCSRCS})
else()
Expand All @@ -140,13 +142,15 @@ set_target_properties(notcurses-static PROPERTIES
target_include_directories(notcurses
PRIVATE
include
src
"${PROJECT_BINARY_DIR}/include"
"${TERMINFO_INCLUDE_DIRS}"
"${READLINE_INCLUDE_DIRS}"
)
target_include_directories(notcurses-static
PRIVATE
include
src
"${PROJECT_BINARY_DIR}/include"
"${TERMINFO_STATIC_INCLUDE_DIRS}"
"${READLINE_STATIC_INCLUDE_DIRS}"
Expand Down Expand Up @@ -379,6 +383,7 @@ target_compile_definitions(notcurses-demo
target_include_directories(notcurses-demo
PRIVATE
include
src
"${PROJECT_BINARY_DIR}/include"
PUBLIC
"${AVCODEC_INCLUDE_DIRS}"
Expand All @@ -400,7 +405,7 @@ foreach(f ${POCSRCS})
get_filename_component(fe "${f}" NAME_WE)
add_executable(${fe} ${f})
target_include_directories(${fe}
PRIVATE include "${TERMINFO_INCLUDE_DIRS}"
PRIVATE include src "${TERMINFO_INCLUDE_DIRS}"
"${PROJECT_BINARY_DIR}/include"
)
target_link_libraries(${fe}
Expand Down Expand Up @@ -548,6 +553,7 @@ add_executable(notcurses-view ${VIEWSRCS})
target_include_directories(notcurses-view
PRIVATE
include
src
"${PROJECT_BINARY_DIR}/include"
)
target_link_libraries(notcurses-view
Expand All @@ -565,6 +571,7 @@ add_executable(notcurses-tester ${TESTSRCS})
target_include_directories(notcurses-tester
PRIVATE
include
src
"${PROJECT_BINARY_DIR}/include"
src/lib
)
Expand Down
28 changes: 28 additions & 0 deletions src/compat/compat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef __linux__
#ifndef __FreeBSD__
#include <time.h>
// clock_nanosleep is unavailable on DragonFly BSD and Mac OS X
int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *request,
struct timespec *remain){
struct timespec now;
if(clock_gettime(clockid, &now)){
return -1;
}
uint64_t nowns = timespec_to_ns(&now);
uint64_t targns = timespec_to_ns(&request);
if(flags != TIMER_ABSTIME){
targns += nowns;
}
if(nowns < targns){
uint64_t waitns = targns - nowns;
struct timespec waitts = {
.tv_sec = waitns / 1000000000,
.tv_nsec = waitns % 1000000000,
};
return nanosleep(&waitts, remain);
}
return 0;

}
#endif
#endif
27 changes: 27 additions & 0 deletions src/compat/compat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef NOTCURSES_COMPAT
#define NOTCURSES_COMPAT

#include <time.h>

#define NANOSECS_IN_SEC 1000000000ul

static inline uint64_t
timespec_to_ns(const struct timespec* ts){
return ts->tv_sec * NANOSECS_IN_SEC + ts->tv_nsec;
}

static inline struct timespec*
ns_to_timespec(uint64_t ns, struct timespec* ts){
ts->tv_sec = ns / NANOSECS_IN_SEC;
ts->tv_nsec = ns % NANOSECS_IN_SEC;
return ts;
}

// compatibility wrappers for code available only on certain operating systems.
// this file is not installed, but only consumed during compilation. if we're
// on an operating system which implements a given function, it won't be built.
int clock_nanosleep(clockid_t clockid, int flags,
const struct timespec *request,
struct timespec *remain);

#endif
22 changes: 11 additions & 11 deletions src/demo/demo.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,9 +332,9 @@ handle_opts(int argc, char** argv, notcurses_options* opts,
usage(*argv, EXIT_FAILURE);
}
delaymultiplier = f;
uint64_t ns = f * GIG;
demodelay.tv_sec = ns / GIG;
demodelay.tv_nsec = ns % GIG;
uint64_t ns = f * NANOSECS_IN_SEC;
demodelay.tv_sec = ns / NANOSECS_IN_SEC;
demodelay.tv_nsec = ns % NANOSECS_IN_SEC;
break;
}default:
usage(*argv, EXIT_FAILURE);
Expand Down Expand Up @@ -424,15 +424,15 @@ summary_table(struct ncdirect* nc, const char* spec, bool canimage, bool canvide
uint64_t nsdelta = 0;
for(size_t i = 0 ; i < strlen(spec) ; ++i){
nsdelta += results[i].timens;
qprefix(results[i].timens, GIG, timebuf, 0);
qprefix(results[i].stats.render_ns, GIG, rtimebuf, 0);
qprefix(results[i].timens, NANOSECS_IN_SEC, timebuf, 0);
qprefix(results[i].stats.render_ns, NANOSECS_IN_SEC, rtimebuf, 0);
bprefix(results[i].stats.render_bytes, 1, totalbuf, 0);
if(results[i].stats.renders){
qprefix((uintmax_t)results[i].stats.renders * GIG * 1000 /
qprefix((uintmax_t)results[i].stats.renders * NANOSECS_IN_SEC * 1000 /
(results[i].stats.render_ns + results[i].stats.writeout_ns),
1000, tfpsbuf, 0);
}else{
qprefix(0, GIG, tfpsbuf, 0);
qprefix(0, NANOSECS_IN_SEC, tfpsbuf, 0);
}
uint32_t rescolor;
if(results[i].result < 0){
Expand All @@ -455,7 +455,7 @@ summary_table(struct ncdirect* nc, const char* spec, bool canimage, bool canvide
PREFIXFMT(timebuf), (uintmax_t)(results[i].stats.renders),
BPREFIXFMT(totalbuf), PREFIXFMT(rtimebuf),
results[i].timens ?
results[i].stats.renders / ((double)results[i].timens / GIG) : 0.0,
results[i].stats.renders / ((double)results[i].timens / NANOSECS_IN_SEC) : 0.0,
(uintmax_t)(results[i].timens ?
results[i].stats.render_ns * 100 / results[i].timens : 0),
(uintmax_t)(results[i].timens ?
Expand All @@ -473,16 +473,16 @@ summary_table(struct ncdirect* nc, const char* spec, bool canimage, bool canvide
totalrenderns += results[i].stats.render_ns;
totalwriteoutns += results[i].stats.writeout_ns;
}
qprefix(nsdelta, GIG, timebuf, 0);
qprefix(nsdelta, NANOSECS_IN_SEC, timebuf, 0);
bprefix(totalbytes, 1, totalbuf, 0);
qprefix(totalrenderns, GIG, rtimebuf, 0);
qprefix(totalrenderns, NANOSECS_IN_SEC, rtimebuf, 0);
table_segment(nc, "", "══╧════════╧════════╪═══════╪═════════╪═════════╪═══════╪══╧══╧═══════╝\n");
printf(" ");
table_printf(nc, "│", "%*ss", PREFIXFMT(timebuf));
table_printf(nc, "│", "%7lu", totalframes);
table_printf(nc, "│", "%*s", BPREFIXFMT(totalbuf));
table_printf(nc, "│", " %*ss", PREFIXFMT(rtimebuf));
table_printf(nc, "│", "%7.1f", nsdelta ? totalframes / ((double)nsdelta / GIG) : 0);
table_printf(nc, "│", "%7.1f", nsdelta ? totalframes / ((double)nsdelta / NANOSECS_IN_SEC) : 0);
printf("\n");
ncdirect_set_fg_rgb8(nc, 0xff, 0xb0, 0xb0);
fflush(stdout); // in case we print to stderr below, we want color from above
Expand Down
24 changes: 6 additions & 18 deletions src/demo/demo.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <notcurses/notcurses.h>
#include <builddef.h>
#include <version.h>
#include "compat/compat.h"

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -88,20 +89,7 @@ demo_getc_blocking(struct notcurses* nc, ncinput* ni){
/*----------------------------- end demo input API -------------------------*/

/*-------------------------------time helpers----------------------------*/
#define GIG 1000000000ul
#define MAXSLEEP (GIG / 80) // nanoseconds

static inline uint64_t
timespec_to_ns(const struct timespec* ts){
return ts->tv_sec * GIG + ts->tv_nsec;
}

static inline struct timespec*
ns_to_timespec(uint64_t ns, struct timespec* ts){
ts->tv_sec = ns / GIG;
ts->tv_nsec = ns % GIG;
return ts;
}
#define MAXSLEEP (NANOSECS_IN_SEC / 80) // nanoseconds

static inline int64_t
timespec_subtract_ns(const struct timespec* time1, const struct timespec* time0){
Expand Down Expand Up @@ -130,17 +118,17 @@ static inline void
timespec_div(const struct timespec* ts, unsigned divisor, struct timespec* quots){
uint64_t ns = timespec_to_ns(ts);
ns /= divisor;
quots->tv_nsec = ns % GIG;
quots->tv_sec = ns / GIG;
quots->tv_nsec = ns % NANOSECS_IN_SEC;
quots->tv_sec = ns / NANOSECS_IN_SEC;
}

// divide the provided timespec 'ts' by 'multiplier' into 'product'
static inline void
timespec_mul(const struct timespec* ts, unsigned multiplier, struct timespec* product){
uint64_t ns = timespec_to_ns(ts);
ns *= multiplier;
product->tv_nsec = ns % GIG;
product->tv_sec = ns / GIG;
product->tv_nsec = ns % NANOSECS_IN_SEC;
product->tv_sec = ns / NANOSECS_IN_SEC;
}
/*-------------------------------time helpers----------------------------*/

Expand Down
12 changes: 6 additions & 6 deletions src/demo/hud.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,8 @@ hud_print_finished(elem* list){
if(ncplane_printf_yx(hud, line, 1, "%d", e->frames) < 0){
return -1;
}
if(ncplane_printf_yx(hud, line, 7, "%ju.%03jus", e->totalns / GIG,
(e->totalns % GIG) / 1000000) < 0){
if(ncplane_printf_yx(hud, line, 7, "%ju.%03jus", e->totalns / NANOSECS_IN_SEC,
(e->totalns % NANOSECS_IN_SEC) / 1000000) < 0){
return -1;
}
if(ncplane_putstr_yx(hud, line, 16, e->name) < 0){
Expand Down Expand Up @@ -516,7 +516,7 @@ demo_nanosleep_abstime_ns(struct notcurses* nc, uint64_t deadline){
while(deadline > timespec_to_ns(&now)){
fsleep.tv_sec = 0;
fsleep.tv_nsec = MAXSLEEP;
if(deadline - timespec_to_ns(&now) < GIG / 100){
if(deadline - timespec_to_ns(&now) < NANOSECS_IN_SEC / 100){
fsleep.tv_nsec = deadline - timespec_to_ns(&now);
}
ncinput ni;
Expand Down Expand Up @@ -565,7 +565,7 @@ int demo_render(struct notcurses* nc){
if(!plot_hidden){
ncplane_move_top(ncuplot_plane(plot));
}
uint64_t ns = (timespec_to_ns(&ts) - plottimestart) / (GIG / FPSHZ);
uint64_t ns = (timespec_to_ns(&ts) - plottimestart) / (NANOSECS_IN_SEC / FPSHZ);
ncuplot_add_sample(plot, ns, 1);
}
if(menu){
Expand All @@ -588,8 +588,8 @@ int demo_render(struct notcurses* nc){
if(ncplane_printf_yx(hud, 1, 1, "%d", elems->frames) < 0){
return -1;
}
if(ncplane_printf_yx(hud, 1, 7, "%ju.%03jus", ns / GIG,
(ns % GIG) / 1000000) < 0){
if(ncplane_printf_yx(hud, 1, 7, "%ju.%03jus", ns / NANOSECS_IN_SEC,
(ns % NANOSECS_IN_SEC) / 1000000) < 0){
return -1;
}
if(ncplane_putstr_yx(hud, 1, 16, elems->name) < 0){
Expand Down
2 changes: 1 addition & 1 deletion src/demo/jungle.c
Original file line number Diff line number Diff line change
Expand Up @@ -26634,7 +26634,7 @@ int jungle_demo(struct notcurses* nc){
free(buf);
clock_gettime(CLOCK_MONOTONIC_RAW, &start);
int iter = 0;
int64_t iterns = GIG / 30;
int64_t iterns = NANOSECS_IN_SEC / 30;
int64_t nsrunning;
do{
DEMO_RENDER(nc);
Expand Down
4 changes: 2 additions & 2 deletions src/demo/sliding.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ play(struct notcurses* nc, struct ncplane** chunks){
int lastdir = -1;
for(m = 0 ; m < MOVES ; ++m){
clock_gettime(CLOCK_MONOTONIC, &cur);
uint64_t now = cur.tv_sec * GIG + cur.tv_nsec;
uint64_t now = cur.tv_sec * NANOSECS_IN_SEC + cur.tv_nsec;
if(now >= deadline_ns){
break;
}
Expand Down Expand Up @@ -189,7 +189,7 @@ int sliding_puzzle_demo(struct notcurses* nc){
goto done;
}
DEMO_RENDER(nc);
struct timespec ts = { .tv_sec = 0, .tv_nsec = GIG, };
struct timespec ts = { .tv_sec = 0, .tv_nsec = NANOSECS_IN_SEC, };
// fade out each of the chunks in succession
/*for(cy = 0 ; cy < CHUNKS_VERT ; ++cy){
for(cx = 0 ; cx < CHUNKS_HORZ ; ++cx){
Expand Down
6 changes: 3 additions & 3 deletions src/demo/whiteout.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ message(struct ncplane* n, int maxy, int maxx, int num, int total,
ncplane_printf_yx(n, 1, 4, " %03dx%03d (%d/%d) ", maxx, maxy, num + 1, total);
ncplane_off_styles(n, NCSTYLE_ITALIC);
ncplane_set_fg_rgb8(n, 224, 128, 224);
ncplane_putstr_yx(n, 3, 1, " 🔥 unicode 13, resize awareness, 24b truecolor…🔥 ");
ncplane_putstr_yx(n, 3, 1, " 🎆🔥 unicode 13, resize awareness, 24b truecolor…🔥🎆 ");
ncplane_set_fg_rgb8(n, 255, 255, 255);
return 0;
}
Expand Down Expand Up @@ -555,8 +555,8 @@ int witherworm_demo(struct notcurses* nc){
uint64_t delay = timespec_to_ns(&demodelay);
delay /= screens;
struct timespec tv;
if(delay > GIG){
ns_to_timespec(GIG, &tv);
if(delay > NANOSECS_IN_SEC){
ns_to_timespec(NANOSECS_IN_SEC, &tv);
}else{
ns_to_timespec(delay, &tv);
}
Expand Down
15 changes: 1 addition & 14 deletions src/lib/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const char* oiio_version(void);
#include <langinfo.h>
#include <netinet/in.h>
#include "notcurses/notcurses.h"
#include "compat/compat.h"
#include "egcpool.h"

struct esctrie;
Expand Down Expand Up @@ -606,20 +607,6 @@ ncplane_cell_ref_yx(ncplane* n, int y, int x){
return &n->fb[nfbcellidx(n, y, x)];
}

#define NANOSECS_IN_SEC 1000000000

static inline uint64_t
timespec_to_ns(const struct timespec* t){
return t->tv_sec * NANOSECS_IN_SEC + t->tv_nsec;
}

static inline struct timespec*
ns_to_timespec(uint64_t ns, struct timespec* ts){
ts->tv_sec = ns / NANOSECS_IN_SEC;
ts->tv_nsec = ns % NANOSECS_IN_SEC;
return ts;
}

static inline void
cell_debug(const egcpool* p, const nccell* c){
fprintf(stderr, "gcluster: %u %s style: 0x%04x chan: 0x%016jx\n",
Expand Down
1 change: 1 addition & 0 deletions src/poc/blitters.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <unistd.h>
#include <locale.h>
#include <notcurses/notcurses.h>
#include "compat/compat.h"

int main(int argc, char** argv){
if(setlocale(LC_ALL, "") == NULL){
Expand Down
1 change: 1 addition & 0 deletions src/poc/pixels.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <locale.h>
#include <notcurses/notcurses.h>
#include "compat/compat.h"

int main(void){
setlocale(LC_ALL, "");
Expand Down
1 change: 1 addition & 0 deletions src/poc/rotator.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <stdlib.h>
#include <locale.h>
#include <notcurses/notcurses.h>
#include "compat/compat.h"

static int
rotate_grad(struct notcurses* nc){
Expand Down
1 change: 1 addition & 0 deletions src/poc/visual.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <cassert>
#include <unistd.h>
#include <notcurses/notcurses.h>
#include "compat/compat.h"

int main(int argc, char** argv){
struct timespec ts = {
Expand Down

0 comments on commit 8283adc

Please sign in to comment.