refactor: migrate MICRO_PIP to fine-grained feature flags

Replace monolithic MICRO_PIP/PIP_MICRO with granular flags:

Feature flags (CMake options + platform auto-detection):
- PIP_NO_FILESYSTEM, PIP_NO_THREADS, PIP_NO_SOCKET
- PIP_NO_PROCESS, PIP_NO_DYNLIB, PIP_NO_FFT, PIP_NO_SERIAL

Embedded optimization flag:
- PIP_EMBEDDED (auto-set for Pico SDK and FreeRTOS)
  Controls buffer sizes, time stubs, terminal fallback, init stubs

Platform blocks in CMakeLists.txt:
- Pico SDK: auto-disables FS, PROCESS, DYNLIB, FFT, SERIAL;
  conditionally disables THREADS (no FreeRTOS) and SOCKET (no LWIP)
- FreeRTOS: auto-disables FS, PROCESS, DYNLIB, FFT, SERIAL;
  conditionally disables SOCKET (no LWIP)
- Android: auto-disables PROCESS, DYNLIB, FFT

Updated 96 files across libs/, utils/, tests/, and CMakeLists.txt.
Builds verified for Linux (547 tests pass) and Pico SDK (100%).
Removed all MICRO_PIP and PIP_MICRO references (0 remaining).
This commit is contained in:
2026-08-11 14:34:59 +03:00
parent 87c53d45a4
commit 4d8b743075
97 changed files with 1555 additions and 914 deletions
+14 -9
View File
@@ -1,6 +1,6 @@
/*
PIP - Platform Independent Primitives
High-level log
High-level log
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
@@ -24,6 +24,8 @@
#include "piliterals_time.h"
#include "pitime.h"
#ifndef PIP_NO_THREADS
# ifndef PIP_NO_FILESYSTEM
//! \class PILog pilog.h
//! \details
@@ -124,12 +126,12 @@ PIStringList PILog::readAllLogs() const {
auto it = names.makeIterator();
bool was_own = false;
auto readFile = [&ret](PIFile * f) {
PIIOTextStream ts(f);
PIString line;
while (!ts.isEnd()) {
line = ts.readLine().trim();
if (line.isNotEmpty()) ret << line;
}
PIIOTextStream ts(f);
PIString line;
while (!ts.isEnd()) {
line = ts.readLine().trim();
if (line.isNotEmpty()) ret << line;
}
};
while (it.next()) {
PIFile * f = nullptr;
@@ -203,8 +205,8 @@ void PILog::newFile() {
PIString aname = log_name;
if (aname.isNotEmpty()) aname += "__";
log_file.open(log_dir + "/" + aname + PIDateTime::current().toString("yyyy_MM_dd__hh_mm_ss") + ".log." +
PIString::fromNumber(++part_number),
PIIODevice::ReadWrite);
PIString::fromNumber(++part_number),
PIIODevice::ReadWrite);
}
@@ -245,3 +247,6 @@ void PILog::run() {
}
}
}
# endif // PIP_NO_FILESYSTEM
#endif // PIP_NO_THREADS
+7 -1
View File
@@ -29,6 +29,9 @@
#include "piiostream.h"
#include "pithread.h"
#ifndef PIP_NO_THREADS
# ifndef PIP_NO_FILESYSTEM
//! \~\ingroup Application
//! \~\brief
//! \~english High-level log
@@ -184,4 +187,7 @@ private:
int part_number = -1, cout_id = -1;
};
#endif
# endif // PIP_NO_FILESYSTEM
#endif // PIP_NO_THREADS
#endif // PIlog_H
@@ -24,6 +24,7 @@
#include "pisharedmemory.h"
#include "pitime.h"
#ifndef PIP_NO_THREADS
//! \class PISingleApplication pisingleapplication.h
//! \~\details
@@ -64,7 +65,7 @@
//!
#define SHM_SIZE 32_KiB
# define SHM_SIZE 32_KiB
PISingleApplication::PISingleApplication(const PIString & app_name): PIThread() {
@@ -150,3 +151,5 @@ void PISingleApplication::waitFirst() const {
while (!started)
piMSleep(50);
}
#endif // PIP_NO_THREADS
@@ -29,6 +29,8 @@
class PISharedMemory;
#ifndef PIP_NO_THREADS
//! \~\ingroup Application
//! \~\brief
//! \~english Single-instance application control.
@@ -92,4 +94,5 @@ private:
int sacnt;
};
#endif // PIP_NO_THREADS
#endif // PISINGLEAPPLICATION_H
+56 -53
View File
@@ -40,6 +40,7 @@ struct kqueue_id_t;
# include "esp_heap_caps.h"
#endif
#ifndef PIP_NO_THREADS
void PISystemMonitor::ProcessStats::makeStrings() {
physical_memsize_readable.setReadableSize(physical_memsize);
@@ -50,43 +51,43 @@ void PISystemMonitor::ProcessStats::makeStrings() {
}
#ifndef MICRO_PIP
# ifndef PIP_NO_PROCESS
PRIVATE_DEFINITION_START(PISystemMonitor)
# ifndef WINDOWS
# ifdef MAC_OS
# ifndef WINDOWS
# ifdef MAC_OS
PISystemTime
# else
# else
llong
# endif
# endif
cpu_u_cur,
cpu_u_prev, cpu_s_cur, cpu_s_prev;
PIString proc_dir;
PIFile file, filem;
# else
# else
HANDLE hProc;
PROCESS_MEMORY_COUNTERS mem_cnt;
PISystemTime tm_kernel, tm_user;
PITimeMeasurer tm;
# endif
# endif
PRIVATE_DEFINITION_END(PISystemMonitor)
#endif
# endif // PIP_NO_PROCESS
PISystemMonitor::PISystemMonitor(): PIThread() {
pID_ = cycle = 0;
cpu_count = PISystemInfo::instance()->processorsCount;
#ifndef MICRO_PIP
# ifndef WINDOWS
# ifdef QNX
# ifndef PIP_NO_PROCESS
# ifndef WINDOWS
# ifdef QNX
page_size = 4096;
# else
# else
page_size = getpagesize();
# endif
# else
# endif
# else
PRIVATE->hProc = 0;
PRIVATE->mem_cnt.cb = sizeof(PRIVATE->mem_cnt);
# endif
#endif
# endif
# endif // PIP_NO_PROCESS
setName("system_monitor"_a);
}
@@ -96,14 +97,14 @@ PISystemMonitor::~PISystemMonitor() {
}
#ifndef MICRO_PIP
# ifndef PIP_NO_PROCESS
bool PISystemMonitor::startOnProcess(int pID, PISystemTime interval) {
stop();
pID_ = pID;
Pool::instance()->add(this);
cycle = -1;
# ifndef WINDOWS
# ifndef MAC_OS
# ifndef WINDOWS
# ifndef MAC_OS
PRIVATE->proc_dir = PIStringAscii("/proc/") + PIString::fromNumber(pID_) + PIStringAscii("/");
PRIVATE->file.open(PRIVATE->proc_dir + "stat", PIIODevice::ReadOnly);
PRIVATE->filem.open(PRIVATE->proc_dir + "statm", PIIODevice::ReadOnly);
@@ -111,27 +112,27 @@ bool PISystemMonitor::startOnProcess(int pID, PISystemTime interval) {
piCoutObj << "Can`t find process with ID = %1!"_tr("PISystemMonitor").arg(pID_);
return false;
}
# endif
# else
# endif
# else
PRIVATE->hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pID_);
if (PRIVATE->hProc == 0) {
piCoutObj << "Can`t open process with ID = %1, %2!"_tr("PISystemMonitor").arg(pID_).arg(errorString());
return false;
}
PRIVATE->tm.reset();
# endif
# endif
return start(interval);
}
#endif
# endif // PIP_NO_PROCESS
bool PISystemMonitor::startOnSelf(PISystemTime interval) {
#ifndef MICRO_PIP
# ifndef PIP_NO_PROCESS
bool ret = startOnProcess(PIProcess::currentPID(), interval);
cycle = -1;
#else
# else
bool ret = start(interval);
#endif
# endif // PIP_NO_PROCESS
return ret;
}
@@ -153,12 +154,12 @@ void PISystemMonitor::setStatistic(const PISystemMonitor::ProcessStats & s) {
void PISystemMonitor::stop() {
PIThread::stopAndWait();
#ifdef WINDOWS
# ifdef WINDOWS
if (PRIVATE->hProc != 0) {
CloseHandle(PRIVATE->hProc);
PRIVATE->hProc = 0;
}
#endif
# endif
Pool::instance()->remove(this);
}
@@ -169,18 +170,18 @@ PISystemMonitor::ProcessStats PISystemMonitor::statistic() const {
}
#ifdef MAC_OS
# ifdef MAC_OS
PISystemTime uint64toST(uint64_t v) {
return PISystemTime(((uint *)&(v))[1], ((uint *)&(v))[0]);
}
#endif
# endif
void PISystemMonitor::run() {
cur_tm.clear();
tbid.clear();
ProcessStats tstat;
tstat.ID = pID_;
#ifndef PIP_NO_THREADS
# ifndef PIP_NO_THREADS
__PIThreadCollection * pitc = __PIThreadCollection::instance();
pitc->lock();
PIVector<PIThread *> tv = pitc->threads();
@@ -188,14 +189,14 @@ void PISystemMonitor::run() {
if (t->isPIObject()) tbid[t->tid()] = t->name();
pitc->unlock();
// piCout << tbid.keys().toType<uint>();
# ifdef FREERTOS
# ifdef FREERTOS
for (auto * t: tv)
if (t->isPIObject()) gatherThread(t->tid());
# else // FREERTOS
# ifndef WINDOWS
# else // FREERTOS
# ifndef WINDOWS
double delay_ms = delay_.toMilliseconds();
tbid[pID_] = "main";
# ifdef MAC_OS
# ifdef MAC_OS
rusage_info_current ru;
proc_pid_rusage(pID_, RUSAGE_INFO_CURRENT, (rusage_info_t *)&ru);
// piCout << PISystemTime(((uint*)&(ru.ri_user_time))[1], ((uint*)&(ru.ri_user_time))[0]);
@@ -211,7 +212,7 @@ void PISystemMonitor::run() {
tstat.cpu_load_user = 100.f * (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_ms;
cycle = 0;
// piCout << (PRIVATE->cpu_u_cur - PRIVATE->cpu_u_prev).toMilliseconds() / delay_ms;
# else // MAC_OS
# else // MAC_OS
PRIVATE->file.seekToBegin();
PIString str = PIString::fromAscii(PRIVATE->file.readAll());
int si = str.find('(') + 1, fi = 0, cc = 1;
@@ -265,8 +266,8 @@ void PISystemMonitor::run() {
if (i.flags[PIFile::FileInfo::Dot] || i.flags[PIFile::FileInfo::DotDot]) continue;
gatherThread(i.name().toInt());
}
# endif // MAC_OS
# else // WINDOWS
# endif // MAC_OS
# else // WINDOWS
if (GetProcessMemoryInfo(PRIVATE->hProc, &PRIVATE->mem_cnt, sizeof(PRIVATE->mem_cnt)) != 0) {
tstat.physical_memsize = PRIVATE->mem_cnt.WorkingSetSize;
}
@@ -316,9 +317,9 @@ void PISystemMonitor::run() {
tstat.cpu_load_user = 0.f;
}
PRIVATE->tm.reset();
# endif // WINDOWS
# endif // FREERTOS
#endif // PIP_NO_THREADS
# endif // WINDOWS
# endif // FREERTOS
# endif // PIP_NO_THREADS
tstat.cpu_load_system = piClampf(tstat.cpu_load_system, 0.f, 100.f);
tstat.cpu_load_user = piClampf(tstat.cpu_load_user, 0.f, 100.f);
@@ -351,11 +352,11 @@ void PISystemMonitor::gatherThread(llong id) {
PISystemMonitor::ThreadStats ts;
if (id == 0) return;
ts.id = id;
#ifdef MICRO_PIP
# ifdef PIP_NO_PROCESS
ts.name = tbid.value(id, "<PIThread>");
#else
# else
ts.name = tbid.value(id, "<non-PIThread>");
# ifndef WINDOWS
# ifndef WINDOWS
PIFile f(PRIVATE->proc_dir + "task/" + PIString::fromNumber(id) + "/stat");
// piCout << f.path();
if (!f.open(PIIODevice::ReadOnly)) return;
@@ -375,7 +376,7 @@ void PISystemMonitor::gatherThread(llong id) {
// piCout << sl[0] << sl[12] << sl[13];
ts.user_time = PISystemTime::fromMilliseconds(sl[12].toInt() * 10.);
ts.kernel_time = PISystemTime::fromMilliseconds(sl[13].toInt() * 10.);
# else
# else
PISystemTime ct = PISystemTime::current();
FILETIME times[4];
HANDLE thdl = OpenThread(THREAD_QUERY_INFORMATION, FALSE, DWORD(id));
@@ -393,8 +394,8 @@ void PISystemMonitor::gatherThread(llong id) {
ts.work_time = ct - ts.created.toSystemTime();
ts.kernel_time = FILETIME2PISystemTime(times[2]);
ts.user_time = FILETIME2PISystemTime(times[3]);
# endif
#endif
# endif
# endif // PIP_NO_PROCESS
cur_tm[id] = ts;
}
@@ -406,34 +407,34 @@ float PISystemMonitor::calcThreadUsage(PISystemTime & t_new, PISystemTime & t_ol
ullong PISystemMonitor::totalRAM() {
#ifdef ESP_PLATFORM
# ifdef ESP_PLATFORM
multi_heap_info_t heap_info;
piZeroMemory(heap_info);
heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT);
return heap_info.total_allocated_bytes + heap_info.total_free_bytes;
#endif
# endif
return 0;
}
ullong PISystemMonitor::freeRAM() {
#ifdef ESP_PLATFORM
# ifdef ESP_PLATFORM
multi_heap_info_t heap_info;
piZeroMemory(heap_info);
heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT);
return heap_info.total_free_bytes;
#endif
# endif
return 0;
}
ullong PISystemMonitor::usedRAM() {
#ifdef ESP_PLATFORM
# ifdef ESP_PLATFORM
multi_heap_info_t heap_info;
piZeroMemory(heap_info);
heap_caps_get_info(&heap_info, MALLOC_CAP_8BIT);
return heap_info.total_allocated_bytes;
#endif
# endif
return 0;
}
@@ -460,3 +461,5 @@ void PISystemMonitor::Pool::remove(PISystemMonitor * sm) {
PIMutexLocker _ml(mutex);
sysmons.remove(sm->pID());
}
#endif // PIP_NO_THREADS
+8 -6
View File
@@ -28,6 +28,7 @@
#include "pifile.h"
#include "pithread.h"
#ifndef PIP_NO_THREADS
//! \~\ingroup Application
//! \~\brief
@@ -51,7 +52,7 @@ public:
//! \~russian Останавливает мониторинг и отсоединяет объект от текущей цели.
~PISystemMonitor();
#pragma pack(push, 1)
# pragma pack(push, 1)
//! \~\ingroup Application
//! \~\brief
//! \~english Process statistics (fixed-size fields).
@@ -155,7 +156,7 @@ public:
//! \~russian Дата и время создания
PIDateTime created;
};
#pragma pack(pop)
# pragma pack(pop)
//! \~\ingroup Application
//! \~\brief
@@ -205,12 +206,12 @@ public:
PIString name;
};
#ifndef MICRO_PIP
# ifndef PIP_NO_PROCESS
//! \~english Starts monitoring the process with PID "pID" using the given update interval.
//! \~russian Запускает мониторинг процесса с PID "pID" с указанным интервалом обновления.
bool startOnProcess(int pID, PISystemTime interval = PISystemTime::fromSeconds(1.));
#endif
# endif // PIP_NO_PROCESS
//! \~english Starts monitoring the current application process.
//! \~russian Запускает мониторинг текущего процесса приложения.
@@ -271,9 +272,9 @@ private:
PIMap<llong, PIString> tbid;
mutable PIMutex stat_mutex;
int pID_, page_size, cpu_count, cycle;
#ifndef MICRO_PIP
# ifndef PIP_NO_PROCESS
PRIVATE_DECLARATION(PIP_EXPORT)
#endif
# endif // PIP_NO_PROCESS
class PIP_EXPORT Pool {
friend class PISystemMonitor;
@@ -337,4 +338,5 @@ BINARY_STREAM_READ(PISystemMonitor::ThreadStats) {
return s;
}
#endif // PIP_NO_THREADS
#endif // PISYSTEMMONITOR_H
+7 -4
View File
@@ -1,6 +1,6 @@
/*
PIP - Platform Independent Primitives
Translation support
Translation support
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
@@ -25,6 +25,7 @@
#include "pitranslator_p.h"
#include "pivaluetree_conversions.h"
#ifndef PIP_NO_FILESYSTEM
//! \class PITranslator pitranslator.h
//! \details
@@ -64,9 +65,9 @@ void PITranslator::loadLang(const PIString & short_lang, PIString dir) {
auto vt = PIValueTreeConversions::fromText(getBuiltinConfig());
auto lang = vt.child(short_lang.toLowerCase().trim());
for (const auto & cn: lang.children()) {
auto c = s->PRIVATEWB->content.createContext(cn.name());
for (const auto & s: cn.children())
c->add(s.name(), s.value().toString());
auto c = s->PRIVATEWB->content.createContext(cn.name());
for (const auto & s: cn.children())
c->add(s.name(), s.value().toString());
}*/
}
@@ -114,3 +115,5 @@ PITranslator * PITranslator::instance() {
static PITranslator ret;
return &ret;
}
#endif // PIP_NO_FILESYSTEM
+2
View File
@@ -153,6 +153,7 @@ bool PICodeParser::isEnum(const PIString & name) {
}
#ifndef PIP_NO_FILESYSTEM
bool PICodeParser::parseFileInternal(const PIString & file, bool follow_includes) {
if (proc_files[file]) return true;
with_includes = follow_includes;
@@ -178,6 +179,7 @@ bool PICodeParser::parseFileInternal(const PIString & file, bool follow_includes
piCout << "parsing" << f.path() << "done";
return ret;
}
#endif // PIP_NO_FILESYSTEM
void PICodeParser::clear() {
+2 -2
View File
@@ -18,7 +18,7 @@
*/
#include "pikbdlistener.h"
#ifndef MICRO_PIP
#ifndef PIP_NO_THREADS
# include "piincludes_p.h"
# include "piliterals.h"
@@ -590,4 +590,4 @@ void PIKbdListener::setActive(bool yes) {
}
}
#endif // MICRO_PIP
#endif // PIP_NO_THREADS
+8 -8
View File
@@ -27,7 +27,7 @@
#include "pibase.h"
#ifndef MICRO_PIP
#ifndef PIP_NO_THREADS
# include "pithread.h"
# include "pitime.h"
@@ -36,12 +36,12 @@
//! \~\brief
//! \~english Waits until the active listener captures the configured exit key and then stops it.
//! \~russian Ожидает, пока активный слушатель перехватит настроенную клавишу выхода, и затем останавливает его.
# define WAIT_FOR_EXIT \
while (!PIKbdListener::exiting) \
piMSleep(PIP_MIN_MSLEEP * 5); \
if (PIKbdListener::instance()) { \
if (!PIKbdListener::instance()->stopAndWait(PISystemTime::fromSeconds(1))) PIKbdListener::instance()->terminate(); \
}
# define WAIT_FOR_EXIT \
while (!PIKbdListener::exiting) \
piMSleep(PIP_MIN_MSLEEP * 5); \
if (PIKbdListener::instance()) { \
if (!PIKbdListener::instance()->stopAndWait(PISystemTime::fromSeconds(1))) PIKbdListener::instance()->terminate(); \
}
//! \~\ingroup Console
@@ -381,5 +381,5 @@ REGISTER_PIVARIANTSIMPLE(PIKbdListener::KeyEvent)
REGISTER_PIVARIANTSIMPLE(PIKbdListener::MouseEvent)
REGISTER_PIVARIANTSIMPLE(PIKbdListener::WheelEvent)
#endif // MICRO_PIP
#endif // PIP_NO_THREADS
#endif // PIKBDLISTENER_H
+5 -4
View File
@@ -34,6 +34,7 @@
//! \~\brief
//! \~english Console screen manager with tile layout, drawing, and input routing.
//! \~russian Менеджер консольного экрана с раскладкой тайлов, отрисовкой и маршрутизацией ввода.
#if !defined(PICO_SDK)
class PIP_CONSOLE_EXPORT PIScreen
: public PIThread
, public PIScreenTypes::PIScreenBase {
@@ -177,14 +178,14 @@ private:
void showCursor();
void clearScreen();
void clearScreenLower();
#ifdef WINDOWS
# ifdef WINDOWS
void getWinCurCoord();
void clearLine();
void newLine();
ushort attributes(const PIScreenTypes::Cell & c);
#else
# else
PIString formatString(const PIScreenTypes::Cell & c);
#endif
# endif
PRIVATE_DECLARATION(PIP_CONSOLE_EXPORT)
int width, height, pwidth, pheight;
int mouse_x, mouse_y;
@@ -214,6 +215,6 @@ private:
PIScreenTile root;
PIScreenTile *tile_focus, *tile_dialog;
};
#endif // !PICO_SDK
#endif // PISCREEN_H
+2
View File
@@ -24,6 +24,7 @@
#ifndef PISCREENDRAWER_H
#define PISCREENDRAWER_H
#if !defined(PICO_SDK)
#include "pip_console_export.h"
#include "piscreentypes.h"
@@ -146,4 +147,5 @@ private:
};
#endif // !PICO_SDK
#endif // PISCREENDRAWER_H
+8 -4
View File
@@ -38,6 +38,7 @@ class PIScreenDrawer;
//! \details
//! \~english Base class for all screen tiles providing layout and event handling.
//! \~russian Базовый класс для всех экранных тайлов, обеспечивающий компоновку и обработку событий.
#if !defined(PICO_SDK)
class PIP_CONSOLE_EXPORT PIScreenTile: public PIObject {
friend class PIScreen;
PIOBJECT_SUBCLASS(PIScreenTile, PIObject);
@@ -163,8 +164,10 @@ public:
bool visible;
protected:
//! \~english Returns the preferred tile size in \a w and \a h. The base implementation derives it from visible children, spacing, and margins.
//! \~russian Возвращает предпочтительный размер тайла в \a w и \a h. Базовая реализация вычисляет его по видимым дочерним тайлам, интервалам и отступам.
//! \~english Returns the preferred tile size in \a w and \a h. The base implementation derives it from visible children, spacing, and
//! margins.
//! \~russian Возвращает предпочтительный размер тайла в \a w и \a h. Базовая реализация вычисляет его по видимым дочерним тайлам,
//! интервалам и отступам.
virtual void sizeHint(int & w, int & h) const;
//! \~english Called after the tile size changes to \a w by \a h during layout.
@@ -208,7 +211,8 @@ protected:
void layout();
//! \~english Returns whether this tile should participate in automatic layout. Tiles with policy \a PIScreenTypes::Ignore are skipped.
//! \~russian Возвращает, должен ли тайл участвовать в автоматической компоновке. Тайлы с политикой \a PIScreenTypes::Ignore пропускаются.
//! \~russian Возвращает, должен ли тайл участвовать в автоматической компоновке. Тайлы с политикой \a PIScreenTypes::Ignore
//! пропускаются.
bool needLayout() { return size_policy != PIScreenTypes::Ignore; }
//! \~english Owned direct child tiles.
@@ -234,6 +238,6 @@ protected:
private:
int pw, ph;
};
#endif // !PICO_SDK
#endif // PISCREENTILE_H
+2
View File
@@ -27,6 +27,7 @@
#ifndef PISCREENTILES_H
#define PISCREENTILES_H
#if !defined(PICO_SDK)
#include "pip_console_export.h"
#include "piscreentile.h"
@@ -444,4 +445,5 @@ protected:
};
#endif // !PICO_SDK
#endif // PISCREENTILES_H
+2
View File
@@ -27,6 +27,7 @@
#ifndef PISCREENTYPES_H
#define PISCREENTYPES_H
#if !defined(PICO_SDK)
#include "pip_console_export.h"
#include "pivariant.h"
@@ -284,4 +285,5 @@ BINARY_STREAM_READ(PIScreenTypes::TileEvent) {
REGISTER_PIVARIANTSIMPLE(PIScreenTypes::TileEvent)
#endif // !PICO_SDK
#endif // PISCREENTYPES_H
+2
View File
@@ -24,6 +24,7 @@
#ifndef PITERMINAL_H
#define PITERMINAL_H
#if !defined(PICO_SDK)
#include "pikbdlistener.h"
#include "pip_console_export.h"
@@ -114,4 +115,5 @@ private:
};
#endif // !PICO_SDK
#endif // PITERMINAL_H
+50 -68
View File
@@ -116,10 +116,6 @@
//! \~russian Макрос объявлен когда PIP решил что система поддерживает локализацию
# define HAS_LOCALE
//! \~english Macro is defined when PIP is building for embedded systems
//! \~russian Макрос объявлен когда PIP собирается для встраиваемых систем
# define MICRO_PIP
//! \~english Macro is defined when compiler is Visual Studio
//! \~russian Макрос объявлен когда компилятор Visual Studio
# define CC_VC
@@ -168,7 +164,6 @@
//! \~russian Макрос для подавления предупреждения компилятора о неиспользуемой переменной
# define NO_UNUSED(x)
# undef MICRO_PIP
# undef FREERTOS
#endif // DOXYGEN
@@ -223,12 +218,10 @@ extern char ** environ;
# define assertm(exp, msg) assert(((void)msg, exp))
# endif
# ifdef MICRO_PIP
# define __PIP_TYPENAME__(T) "?"
# elif defined(__GXX_RTTI__) || defined(__RTTI__)
# define __PIP_TYPENAME__(T) typeid(T).name()
# if defined(__GXX_RTTI__) || defined(__RTTI__)
# define __PIP_TYPENAME__(T) typeid(T).name()
# else
# define __PIP_TYPENAME__(T) "?"
# define __PIP_TYPENAME__(T) "?"
# endif
# ifdef CC_GCC
@@ -298,17 +291,17 @@ typedef long long ssize_t;
//! \~english Macro to declare private section, "export" is optional
//! \~russian Макрос для объявления частной секции, "export" необязателен
//! \~sa PRIVATE PRIVATEWB
# define PRIVATE_DECLARATION(e) \
struct __Private__; \
friend struct __Private__; \
struct e __PrivateInitializer__ { \
__PrivateInitializer__(); \
__PrivateInitializer__(const __PrivateInitializer__ & o); \
~__PrivateInitializer__(); \
__PrivateInitializer__ & operator=(const __PrivateInitializer__ & o); \
__Private__ * p = nullptr; \
}; \
__PrivateInitializer__ __privateinitializer__;
# define PRIVATE_DECLARATION(e) \
struct __Private__; \
friend struct __Private__; \
struct e __PrivateInitializer__ { \
__PrivateInitializer__(); \
__PrivateInitializer__(const __PrivateInitializer__ & o); \
~__PrivateInitializer__(); \
__PrivateInitializer__ & operator=(const __PrivateInitializer__ & o); \
__Private__ * p = nullptr; \
}; \
__PrivateInitializer__ __privateinitializer__;
//! \~english Macro to start definition of private section
//! \~russian Макрос для начала реализации частной секции
@@ -318,35 +311,31 @@ typedef long long ssize_t;
//! \~russian Макрос для окончания реализации частной секции без инициализации
//! \~sa PRIVATE_DEFINITION_END PRIVATE_DEFINITION_START PRIVATE_DEFINITION_INITIALIZE PRIVATE PRIVATEWB
# define PRIVATE_DEFINITION_END_NO_INITIALIZE(c) \
} \
;
} \
;
//! \~english Macro to initialize private section
//! \~russian Макрос для инициализации частной секции
//! \~sa PRIVATE_DEFINITION_END PRIVATE_DEFINITION_START PRIVATE_DEFINITION_END_NO_INITIALIZE PRIVATE PRIVATEWB
# define PRIVATE_DEFINITION_INITIALIZE(c) \
c::__PrivateInitializer__::__PrivateInitializer__() { \
p = new c::__Private__(); \
} \
c::__PrivateInitializer__::__PrivateInitializer__(const c::__PrivateInitializer__ &) { /*if (p) delete p;*/ \
p = new c::__Private__(); \
} \
c::__PrivateInitializer__::~__PrivateInitializer__() { \
piDeleteSafety(p); \
} \
c::__PrivateInitializer__ & c::__PrivateInitializer__::operator=(const c::__PrivateInitializer__ &) { \
piDeleteSafety(p); \
p = new c::__Private__(); \
return *this; \
}
# define PRIVATE_DEFINITION_INITIALIZE(c) \
c::__PrivateInitializer__::__PrivateInitializer__() { p = new c::__Private__(); } \
c::__PrivateInitializer__::__PrivateInitializer__(const c::__PrivateInitializer__ &) { /*if (p) delete p;*/ \
p = new c::__Private__(); \
} \
c::__PrivateInitializer__::~__PrivateInitializer__() { piDeleteSafety(p); } \
c::__PrivateInitializer__ & c::__PrivateInitializer__::operator=(const c::__PrivateInitializer__ &) { \
piDeleteSafety(p); \
p = new c::__Private__(); \
return *this; \
}
//! \~english Macro to end definition of private section with initialization
//! \~russian Макрос для окончания реализации частной секции с инициализацией
//! \~sa PRIVATE_DEFINITION_END_NO_INITIALIZE PRIVATE_DEFINITION_START PRIVATE_DEFINITION_INITIALIZE PRIVATE PRIVATEWB
# define PRIVATE_DEFINITION_END(c) \
PRIVATE_DEFINITION_END_NO_INITIALIZE \
(c) PRIVATE_DEFINITION_INITIALIZE(c)
# define PRIVATE_DEFINITION_END(c) \
PRIVATE_DEFINITION_END_NO_INITIALIZE \
(c) PRIVATE_DEFINITION_INITIALIZE(c)
//! \~english Macro to access private section by pointer
//! \~russian Макрос для доступа к частной секции
@@ -362,9 +351,9 @@ typedef long long ssize_t;
//! \~english Macro to remove class copy availability
//! \~russian Макрос для запрета копирования класса
#define NO_COPY_CLASS(name) \
name(const name &) = delete; \
name & operator=(const name &) = delete;
#define NO_COPY_CLASS(name) \
name(const name &) = delete; \
name & operator=(const name &) = delete;
//! \~english Counter macro for unique identifier generation
//! \~russian Макрос счетчика для генерации уникальных идентификаторов
@@ -377,34 +366,19 @@ typedef long long ssize_t;
//! \~russian Макрос для начала статической инициализации
//! \~sa STATIC_INITIALIZER_END
#define STATIC_INITIALIZER_BEGIN \
class { \
class _Initializer_ { \
public: \
_Initializer_() {
class { \
class _Initializer_ { \
public: \
_Initializer_() {
//! \~english Macro to end static initializer
//! \~russian Макрос для окончания статической инициализации
//! \~sa STATIC_INITIALIZER_BEGIN
#define STATIC_INITIALIZER_END \
} \
} \
_initializer_; \
} \
_PIP_ADD_COUNTER(_pip_initializer_);
//! \~english Minimal sleep in milliseconds for internal PIP using
//! \~russian Минимальное значание задержки в милисекундах для внутреннего использования в библиотеке PIP
//! \~\details
//! \~english Using in \a piMinSleep(), \a PIThread, \a PITimer::Pool. By default 1ms.
//! \~russian Используется в \a piMinSleep(), \a PIThread, \a PITimer::Pool. По умолчанию равна 1мс.
//! \~\sa PIP_MIN_MSLEEP
#ifndef PIP_MIN_MSLEEP
# ifndef MICRO_PIP
# define PIP_MIN_MSLEEP 1.
# else
# define PIP_MIN_MSLEEP 10.
# endif
#endif
} \
} \
_initializer_; \
} \
_PIP_ADD_COUNTER(_pip_initializer_);
//! \~english Macro used for infinite loop
@@ -430,4 +404,12 @@ typedef long long ssize_t;
#define WAIT_FOREVER FOREVER piMinSleep();
#ifndef PIP_MIN_MSLEEP
# ifdef PIP_EMBEDDED
# define PIP_MIN_MSLEEP 10.
# else
# define PIP_MIN_MSLEEP 1.
# endif
#endif
#endif // PIBASE_MACROS_H
+28 -26
View File
@@ -367,7 +367,7 @@ void PICout::stdoutPIString(const PIString & str, PICoutStdStream s) {
#ifdef HAS_LOCALE
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> utf8conv;
getStdStream(s) << utf8conv.to_bytes((char16_t *)&(const_cast<PIString &>(str).front()),
(char16_t *)&(const_cast<PIString &>(str).front()) + str.size());
(char16_t *)&(const_cast<PIString &>(str).front()) + str.size());
#else
for (PIChar c: str)
getStdWStream(s).put(c.toWChar());
@@ -409,32 +409,32 @@ void PICout::writeChar(char c) {
}
#define PIINTCOUT(v) \
{ \
if (!actve_) return *this; \
space(); \
if (int_base_ == 10) { \
if (buffer_) { \
(*buffer_) += PIString::fromNumber(v); \
} else { \
if (isOutputDeviceActive(Console)) getStdStream(stream_) << (v); \
if (isOutputDeviceActive(Buffer)) PICout::__string__() += PIString::fromNumber(v); \
} \
} else \
write(PIString::fromNumber(v, int_base_)); \
return *this; \
}
#define PIINTCOUT(v) \
{ \
if (!actve_) return *this; \
space(); \
if (int_base_ == 10) { \
if (buffer_) { \
(*buffer_) += PIString::fromNumber(v); \
} else { \
if (isOutputDeviceActive(Console)) getStdStream(stream_) << (v); \
if (isOutputDeviceActive(Buffer)) PICout::__string__() += PIString::fromNumber(v); \
} \
} else \
write(PIString::fromNumber(v, int_base_)); \
return *this; \
}
#define PIFLOATCOUT(v) \
{ \
if (buffer_) { \
(*buffer_) += PIString::fromNumber(v, 'g'); \
} else { \
if (isOutputDeviceActive(Console)) getStdStream(stream_) << (v); \
if (isOutputDeviceActive(Buffer)) PICout::__string__() += PIString::fromNumber(v, 'g'); \
} \
} \
return *this;
#define PIFLOATCOUT(v) \
{ \
if (buffer_) { \
(*buffer_) += PIString::fromNumber(v, 'g'); \
} else { \
if (isOutputDeviceActive(Console)) getStdStream(stream_) << (v); \
if (isOutputDeviceActive(Buffer)) PICout::__string__() += PIString::fromNumber(v, 'g'); \
} \
} \
return *this;
PICout & PICout::operator<<(const PIString & v) {
@@ -709,6 +709,7 @@ void PICout::applyFormat(PICoutFormat f) {
}
#ifndef PIP_NO_THREADS
PIString PICout::getBuffer() {
PIMutexLocker ml(PICout::__mutex__());
PIString ret = PICout::__string__();
@@ -728,6 +729,7 @@ void PICout::clearBuffer() {
PIMutexLocker ml(PICout::__mutex__());
PICout::__string__().clear();
}
#endif // PIP_NO_THREADS
bool PICout::setOutputDevice(PICout::OutputDevice d, bool on) {
+2 -2
View File
@@ -41,9 +41,9 @@ class PIString;
class PIByteArray;
template<typename P>
class PIBinaryStream;
#ifndef MICRO_PIP
#ifndef _PIP_INIT_STUB_
class PIInit;
#endif
#endif // _PIP_INIT_STUB_
class PIChar;
class PICout;
class PIWaitEvent;
+3 -3
View File
@@ -20,7 +20,7 @@
#include "piinit.h"
#include "piincludes_p.h"
#ifndef MICRO_PIP
#ifndef _PIP_INIT_STUB_
# include "pidir.h"
# include "piobject.h"
@@ -251,7 +251,7 @@ PIInit::PIInit() {
PIStringAscii("FreeBSD");
# elif defined(FREERTOS)
PIStringAscii("FreeRTOS");
# elif defined(MICRO_PIP)
# elif defined(_PIP_INIT_STUB_)
PIStringAscii("MicroPIP");
# else
uns.sysname;
@@ -395,4 +395,4 @@ __PIInit_Initializer__::~__PIInit_Initializer__() {
}
}
#endif // MICRO_PIP
#endif // _PIP_INIT_STUB_
+11 -6
View File
@@ -31,6 +31,11 @@
#include "pibase.h"
// PIInit stub: enabled for embedded or when core features are missing
#if defined(PIP_EMBEDDED) || (defined(PIP_NO_THREADS) && defined(PIP_NO_FILESYSTEM))
# define _PIP_INIT_STUB_
#endif
#ifndef PIP_NO_THREADS
# include "piincludes.h"
@@ -50,11 +55,11 @@ public:
static __PIInit_Initializer__ __piinit_initializer__;
#ifdef MICRO_PIP
#ifndef PIINIT_MICRO_STUB_DEFINED
#define PIINIT_MICRO_STUB_DEFINED
# ifdef _PIP_INIT_STUB_
# ifndef PIINIT_MICRO_STUB_DEFINED
# define PIINIT_MICRO_STUB_DEFINED
int __PIInit_Initializer__::count_ = 0;
int __PIInit_Initializer__::count_ = 0;
PIInit * __PIInit_Initializer__::__instance__ = nullptr;
__PIInit_Initializer__::__PIInit_Initializer__() {
@@ -71,8 +76,8 @@ __PIInit_Initializer__::~__PIInit_Initializer__() {
}
}
#endif
#endif
# endif
# endif
//! \~\ingroup Core
+18 -5
View File
@@ -22,7 +22,7 @@
#include "piconditionvar.h"
#include "pithread.h"
#include "pitime.h"
#ifndef MICRO_PIP
#ifndef PIP_NO_THREADS
# include "pifile.h"
# include "piiostream.h"
# include "pisysteminfo.h"
@@ -176,9 +176,13 @@ PIObject::PIObject(const PIString & name): _signature_(__PIOBJECT_SIGNATURE__),
in_event_cnt = 0;
setName(name);
setDebug(true);
#ifndef PIP_NO_THREADS
mutexObjects().lock();
#endif
objects() << this;
#ifndef PIP_NO_THREADS
mutexObjects().unlock();
#endif
// piCout << "new" << this;
}
@@ -186,9 +190,13 @@ PIObject::PIObject(const PIString & name): _signature_(__PIOBJECT_SIGNATURE__),
PIObject::~PIObject() {
in_event_cnt = 0;
// piCout << "delete" << this;
#ifndef PIP_NO_THREADS
mutexObjects().lock();
#endif
objects().removeAll(this);
#ifndef PIP_NO_THREADS
mutexObjects().unlock();
#endif
deleted(this);
piDisconnectAll();
_signature_ = 0;
@@ -464,7 +472,7 @@ void PIObject::piDisconnect(PIObject * src, const PIString & sig) {
src->connections.remove(i);
i--;
if (dest) {
#if !defined(ANDROID) && !defined(MAC_OS) && !defined(MICRO_PIP)
#if !defined(ANDROID) && !defined(MAC_OS) && !defined(PIP_NO_THREADS)
PIMutexLocker _mld(dest->mutex_connect, src != dest);
#endif
dest->updateConnectors();
@@ -482,7 +490,7 @@ void PIObject::piDisconnectAll() {
// piCout << "disconnect"<< src << o;
if (!o || (o == this)) continue;
if (!o->isPIObject()) continue;
#if !defined(ANDROID) && !defined(MAC_OS) && !defined(MICRO_PIP)
#if !defined(ANDROID) && !defined(MAC_OS) && !defined(PIP_NO_THREADS)
PIMutexLocker _mld(o->mutex_connect, this != o);
#endif
PIVector<Connection> & oc(o->connections);
@@ -547,6 +555,7 @@ PIMap<uint, PIObject::__MetaData> & PIObject::__meta_data() {
}
#ifndef PIP_NO_THREADS
void PIObject::callQueuedEvents() {
mutex_queue.lock();
PIVector<__QueuedEvent> qe = events_queue;
@@ -560,6 +569,7 @@ void PIObject::callQueuedEvents() {
if (e.dest_o->thread_safe_) e.dest_o->mutex_.unlock();
}
}
#endif // PIP_NO_THREADS
//! \details
@@ -570,9 +580,11 @@ void PIObject::callQueuedEvents() {
//! При первом вызове стартует фоновый поток для удаления объектов.
//! Каждый объект из очереди удаляется только когда выйдет из всех
//! событий и обработок.
#ifndef PIP_NO_THREADS
void PIObject::deleteLater() {
Deleter::instance()->post(this);
}
#endif // PIP_NO_THREADS
bool PIObject::findSuitableMethodV(const PIString & method, int args, int & ret_args, PIObject::__MetaFunc & ret) {
@@ -732,7 +744,7 @@ void PIObject::dump(const PIString & line_prefix) const {
}
#ifndef MICRO_PIP
#ifndef PIP_NO_THREADS
void dumpApplication(bool with_objects) {
PIMutexLocker _ml(PIObject::mutexObjects());
// printf("dump application ...\n");
@@ -835,7 +847,7 @@ bool PIObject::Connection::disconnect() const {
return ret;
}
#ifndef PIP_NO_THREADS
PRIVATE_DEFINITION_START(PIObject::Deleter)
PIThread thread;
PIConditionVariable cond_var;
@@ -899,3 +911,4 @@ void PIObject::Deleter::deleteObject(PIObject * o) {
}
// piCout << "[Deleter] delete" << (uintptr_t)o << "done";
}
#endif // PIP_NO_THREADS
+36 -4
View File
@@ -54,7 +54,7 @@
//! требует явного опустошения очереди через \a callQueuedEvents() или
//! \a maybeCallQueuedEvents().
class PIP_EXPORT PIObject {
#ifndef MICRO_PIP
#ifndef PIP_INTROSPECTION
friend class PIObjectManager;
friend PIP_EXPORT void dumpApplication(bool);
friend class PIIntrospection;
@@ -461,7 +461,9 @@ public:
i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender));
} else {
bool ts = sender->thread_safe_;
#ifndef PIP_NO_THREADS
if (ts) i.dest_o->mutex_.lock();
#endif
i.dest_o->eventBegin();
sender->eventBegin();
i.dest_o->emitter_ = sender;
@@ -469,7 +471,9 @@ public:
sender->eventEnd();
if (i.dest_o->isPIObject()) {
i.dest_o->emitter_ = 0;
#ifndef PIP_NO_THREADS
if (ts) i.dest_o->mutex_.unlock();
#endif
i.dest_o->eventEnd();
}
}
@@ -494,7 +498,9 @@ public:
i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl));
} else {
bool ts = sender->thread_safe_;
#ifndef PIP_NO_THREADS
if (ts) i.dest_o->mutex_.lock();
#endif
i.dest_o->eventBegin();
sender->eventBegin();
i.dest_o->emitter_ = sender;
@@ -505,7 +511,9 @@ public:
sender->eventEnd();
if (i.dest_o->isPIObject()) {
i.dest_o->emitter_ = 0;
#ifndef PIP_NO_THREADS
if (ts) i.dest_o->mutex_.unlock();
#endif
i.dest_o->eventEnd();
}
}
@@ -530,7 +538,9 @@ public:
i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl));
} else {
bool ts = sender->thread_safe_;
#ifndef PIP_NO_THREADS
if (ts) i.dest_o->mutex_.lock();
#endif
i.dest_o->eventBegin();
sender->eventBegin();
i.dest_o->emitter_ = sender;
@@ -542,7 +552,9 @@ public:
sender->eventEnd();
if (i.dest_o->isPIObject()) {
i.dest_o->emitter_ = 0;
#ifndef PIP_NO_THREADS
if (ts) i.dest_o->mutex_.unlock();
#endif
i.dest_o->eventEnd();
}
}
@@ -568,7 +580,9 @@ public:
i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl));
} else {
bool ts = sender->thread_safe_;
#ifndef PIP_NO_THREADS
if (ts) i.dest_o->mutex_.lock();
#endif
i.dest_o->eventBegin();
sender->eventBegin();
i.dest_o->emitter_ = sender;
@@ -581,7 +595,9 @@ public:
sender->eventEnd();
if (i.dest_o->isPIObject()) {
i.dest_o->emitter_ = 0;
#ifndef PIP_NO_THREADS
if (ts) i.dest_o->mutex_.unlock();
#endif
i.dest_o->eventEnd();
}
}
@@ -613,7 +629,9 @@ public:
i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl));
} else {
bool ts = sender->thread_safe_;
#ifndef PIP_NO_THREADS
if (ts) i.dest_o->mutex_.lock();
#endif
i.dest_o->eventBegin();
sender->eventBegin();
i.dest_o->emitter_ = sender;
@@ -627,7 +645,9 @@ public:
sender->eventEnd();
if (i.dest_o->isPIObject()) {
i.dest_o->emitter_ = 0;
#ifndef PIP_NO_THREADS
if (ts) i.dest_o->mutex_.unlock();
#endif
i.dest_o->eventEnd();
}
}
@@ -638,6 +658,7 @@ public:
//! \~english Returns the first live object with name "name", or \c nullptr.
//! \~russian Возвращает первый живой объект с именем "name", либо \c nullptr.
#ifndef PIP_NO_THREADS
static PIObject * findByName(const PIString & name) {
PIMutexLocker _ml(mutexObjects());
for (auto * i: PIObject::objects()) {
@@ -646,6 +667,7 @@ public:
}
return nullptr;
}
#endif
//! \~english Returns whether this pointer still refers to a live %PIObject instance.
//! \~russian Возвращает, указывает ли этот указатель на ещё существующий экземпляр %PIObject.
@@ -653,6 +675,7 @@ public:
//! \~english Returns whether this object belongs to class "T" or one of its registered descendants.
//! \~russian Возвращает, принадлежит ли этот объект классу "T" или одному из его зарегистрированных потомков.
#ifndef PIP_NO_THREADS
template<typename T>
bool isTypeOf() const {
if (!isPIObject()) return false;
@@ -667,6 +690,7 @@ public:
if (!isTypeOf<T>()) return (T *)nullptr;
return (T *)this;
}
#endif
//! \~english Returns whether "o" points to a live %PIObject instance.
//! \~russian Возвращает, указывает ли "o" на ещё существующий экземпляр %PIObject.
@@ -796,6 +820,7 @@ private:
PIVector<PIVariantSimple> values;
};
#ifndef PIP_NO_THREADS
class Deleter {
public:
Deleter();
@@ -807,6 +832,7 @@ private:
void deleteObject(PIObject * o);
PRIVATE_DECLARATION(PIP_EXPORT)
};
#endif
bool findSuitableMethodV(const PIString & method, int args, int & ret_args, __MetaFunc & ret);
PIVector<__MetaFunc> findEH(const PIString & name) const;
@@ -830,13 +856,19 @@ private:
PIMap<uint, PIVariant> properties_;
PISet<PIObject *> connectors;
PIVector<__QueuedEvent> events_queue;
PIMutex mutex_, mutex_connect, mutex_queue;
PIObject * emitter_;
bool thread_safe_, proc_event_queue;
std::atomic_int in_event_cnt;
#ifndef PIP_NO_THREADS
PIMutex mutex_, mutex_connect, mutex_queue;
bool thread_safe_, proc_event_queue;
#else
PIMutex mutex_, mutex_connect, mutex_queue;
bool thread_safe_ = false, proc_event_queue = false;
#endif
};
#ifndef MICRO_PIP
#ifndef PIP_NO_THREADS
//! \~english Dumps application-level %PIObject diagnostics.
//! \~russian Выводит диагностическую информацию уровня приложения для %PIObject.
+2 -2
View File
@@ -18,7 +18,7 @@
*/
#include "piwaitevent_p.h"
#ifndef MICRO_PIP
#ifndef PIP_NO_THREADS
# ifdef WINDOWS
// # ifdef _WIN32_WINNT
// # undef _WIN32_WINNT
@@ -154,4 +154,4 @@ void * PIWaitEvent::getEvent() const {
# endif
}
#endif // MICRO_PIP
#endif // PIP_NO_THREADS
+2 -2
View File
@@ -20,7 +20,7 @@
#ifndef PIWAITEVENT_P_H
#define PIWAITEVENT_P_H
#ifndef MICRO_PIP
#ifndef PIP_NO_THREADS
# include "pibase.h"
// clang-format off
@@ -67,5 +67,5 @@ private:
};
#endif // MICRO_PIP
#endif // PIP_NO_THREADS
#endif // PIWAITEVENT_P_H
+12 -8
View File
@@ -23,10 +23,12 @@
#include "piliterals_bytes.h"
#include "piliterals_time.h"
#include "pipropertystorage.h"
#include "pitime.h"
#include "pitranslator.h"
#define PIBINARYLOG_VERSION_OLD 0x31
#ifndef PIP_NO_FILESYSTEM
# include "pitime.h"
# include "pitranslator.h"
# define PIBINARYLOG_VERSION_OLD 0x31
/*! \class PIBinaryLog
* \brief Class for read and write binary data to logfile, and playback this data in realtime, or custom speed
@@ -52,17 +54,17 @@
static const uchar binlog_sig[] = {'B', 'I', 'N', 'L', 'O', 'G'};
#define PIBINARYLOG_VERSION 0x32
#define PIBINARYLOG_SIGNATURE_SIZE sizeof(binlog_sig)
# define PIBINARYLOG_VERSION 0x32
# define PIBINARYLOG_SIGNATURE_SIZE sizeof(binlog_sig)
REGISTER_DEVICE(PIBinaryLog)
PIBinaryLog::PIBinaryLog() {
#ifdef MICRO_PIP
# ifdef PIP_NO_THREADS
setThreadedReadBufferSize(512);
#else
# else
setThreadedReadBufferSize(64_KiB);
#endif
# endif // PIP_NO_THREADS
is_started = is_indexed = is_pause = false;
create_index_on_fly = false;
current_index = -1;
@@ -1008,3 +1010,5 @@ void PIBinaryLog::CompleteIndex::makeIndexPos() {
for (uint i = 0; i < index.size(); i++)
index_pos[index[i].pos] = i;
}
#endif // PIP_NO_FILESYSTEM
+7 -4
View File
@@ -29,6 +29,8 @@
#include "pichunkstream.h"
#include "pifile.h"
#ifndef PIP_NO_FILESYSTEM
//! \~english Class for writing and reading binary data to/from log files, with support for playback in different modes.
//! \~russian Класс для записи и чтения бинарных данных в/из файлов логов с поддержкой воспроизведения в различных режимах.
//! \~\details
@@ -79,7 +81,7 @@ public:
,
};
#pragma pack(push, 8)
# pragma pack(push, 8)
//! \~english Statistics for records sharing the same record ID.
//! \~russian Статистика по записям с одинаковым идентификатором.
@@ -141,7 +143,7 @@ public:
PISystemTime timestamp;
};
#pragma pack(pop)
# pragma pack(pop)
//! \~english Summary information about a log file and its indexed record types.
//! \~russian Сводная информация о файле лога и его индексированных типах записей.
@@ -591,7 +593,7 @@ public:
//! \~russian Возвращает пользовательский заголовок, сохраненный в текущем открытом логе.
PIByteArray getHeader() const;
#ifdef DOXYGEN
# ifdef DOXYGEN
//! \~english Reads one message using \a filterID when it is not empty.
//! \~russian Читает одно сообщение, используя \a filterID, если он не пуст.
int read(void * read_to, int max_size);
@@ -599,7 +601,7 @@ public:
//! \~english Writes one record using \a defaultID().
//! \~russian Записывает одну запись, используя \a defaultID().
int write(const void * data, int size);
#endif
# endif
//! \~english Optional list of record IDs accepted by \a read() and threaded playback.
//! \~russian Необязательный список идентификаторов записей, допустимых для \a read() и потокового воспроизведения.
@@ -991,4 +993,5 @@ inline PICout operator<<(PICout s, const PIBinaryLog::BinLogInfo & bi) {
return s;
}
#endif // PIP_NO_FILESYSTEM
#endif // PIBINARYLOG_H
+12
View File
@@ -288,6 +288,7 @@ PIConfig::PIConfig(PIIODevice * device, PIIODevice::DeviceMode mode) {
}
#ifndef PIP_NO_FILESYSTEM
PIConfig::PIConfig(const PIString & path, PIStringList dirs) {
_init();
internal = true;
@@ -311,6 +312,7 @@ PIConfig::PIConfig(const PIString & path, PIStringList dirs) {
_setupDev();
parse();
}
#endif // PIP_NO_FILESYSTEM
PIConfig::~PIConfig() {
@@ -319,6 +321,7 @@ PIConfig::~PIConfig() {
}
#ifndef PIP_NO_FILESYSTEM
bool PIConfig::open(const PIString & path, PIIODevice::DeviceMode mode) {
_destroy();
incdirs << PIFile::fileInfo(path).dir();
@@ -329,6 +332,7 @@ bool PIConfig::open(const PIString & path, PIIODevice::DeviceMode mode) {
parse();
return dev->isOpened();
}
#endif // PIP_NO_FILESYSTEM
bool PIConfig::open(PIString * string, PIIODevice::DeviceMode mode) {
@@ -347,7 +351,9 @@ bool PIConfig::open(PIIODevice * device, PIIODevice::DeviceMode mode) {
dev = device;
if (dev) {
dev->open(mode);
#ifndef PIP_NO_FILESYSTEM
if (dev->isTypeOf<PIFile>()) incdirs << PIFile::fileInfo(((PIFile *)dev)->path()).dir();
#endif
}
_setupDev();
parse();
@@ -383,10 +389,12 @@ void PIConfig::_setupDev() {
void PIConfig::_clearDev() {
if (!dev) return;
#ifndef PIP_NO_FILESYSTEM
if (PIString(dev->className()) == "PIFile") {
((PIFile *)dev)->clear();
return;
}
#endif
if (PIString(dev->className()) == "PIIOString") {
((PIIOString *)dev)->clear();
((PIIOString *)dev)->setMode(PIIODevice::WriteOnly);
@@ -397,9 +405,11 @@ void PIConfig::_clearDev() {
void PIConfig::_flushDev() {
if (!dev) return;
#ifndef PIP_NO_FILESYSTEM
if (PIString(dev->className()) == "PIFile") {
((PIFile *)dev)->flush();
}
#endif
}
@@ -411,10 +421,12 @@ bool PIConfig::_isEndDev() {
void PIConfig::_seekToBeginDev() {
if (!dev) return;
#ifndef PIP_NO_FILESYSTEM
if (PIString(dev->className()) == "PIFile") {
((PIFile *)dev)->seekToBegin();
return;
}
#endif
if (PIString(dev->className()) == "PIIOString") {
((PIIOString *)dev)->seekToBegin();
((PIIOString *)dev)->setMode(PIIODevice::ReadOnly);
+80 -80
View File
@@ -18,61 +18,61 @@
*/
#ifndef PIP_NO_FILESYSTEM
#include "pifile.h"
# include "pifile.h"
#include "pidir.h"
#include "piincludes_p.h"
#include "piiostream.h"
#include "piliterals_bytes.h"
#include "pitime_win.h"
#include "pitranslator.h"
#ifdef WINDOWS
# undef S_IFDIR
# undef S_IFREG
# undef S_IFLNK
# undef S_IFBLK
# undef S_IFCHR
# undef S_IFSOCK
# define S_IFDIR 0x01
# define S_IFREG 0x02
# define S_IFLNK 0x04
# define S_IFBLK 0x08
# define S_IFCHR 0x10
# define S_IFSOCK 0x20
#else
# include <fcntl.h>
# include <sys/stat.h>
# include <sys/time.h>
# include <utime.h>
#endif
#define S_IFHDN 0x40
#if defined(QNX) || defined(ANDROID) || defined(MICRO_PIP)
# define _fopen_call_ fopen
# define _fseek_call_ fseek
# define _ftell_call_ ftell
# define _stat_struct_ struct stat
# define _stat_call_ stat
# define _stat_link_ lstat
#else
# if defined(MAC_OS)
# define _fopen_call_ fopen
# define _fseek_call_ fseek
# define _ftell_call_ ftell
# include "pidir.h"
# include "piincludes_p.h"
# include "piiostream.h"
# include "piliterals_bytes.h"
# include "pitime_win.h"
# include "pitranslator.h"
# ifdef WINDOWS
# undef S_IFDIR
# undef S_IFREG
# undef S_IFLNK
# undef S_IFBLK
# undef S_IFCHR
# undef S_IFSOCK
# define S_IFDIR 0x01
# define S_IFREG 0x02
# define S_IFLNK 0x04
# define S_IFBLK 0x08
# define S_IFCHR 0x10
# define S_IFSOCK 0x20
# else
# ifdef CC_GCC
# define _fopen_call_ fopen64
# define _fseek_call_ fseeko64
# define _ftell_call_ ftello64
# else
# include <fcntl.h>
# include <sys/stat.h>
# include <sys/time.h>
# include <utime.h>
# endif
# define S_IFHDN 0x40
# if defined(QNX) || defined(ANDROID) || defined(PIP_NO_FILESYSTEM)
# define _fopen_call_ fopen
# define _fseek_call_ fseek
# define _ftell_call_ ftell
# define _stat_struct_ struct stat
# define _stat_call_ stat
# define _stat_link_ lstat
# else
# if defined(MAC_OS)
# define _fopen_call_ fopen
# define _fseek_call_ fseek
# define _ftell_call_ ftell
# else
# ifdef CC_GCC
# define _fopen_call_ fopen64
# define _fseek_call_ fseeko64
# define _ftell_call_ ftello64
# else
# define _fopen_call_ fopen
# define _fseek_call_ fseek
# define _ftell_call_ ftell
# endif
# endif
# define _stat_struct_ struct stat64
# define _stat_call_ stat64
# define _stat_link_ lstat64
# endif
# define _stat_struct_ struct stat64
# define _stat_call_ stat64
# define _stat_link_ lstat64
#endif
//! \class PIFile pifile.h
@@ -176,18 +176,18 @@ PIFile::PIFile(const PIString & path, PIIODevice::DeviceMode mode): PIIODevice(p
bool PIFile::openTemporary(PIIODevice::DeviceMode mode) {
PIString tp;
#ifdef WINDOWS
# ifdef WINDOWS
tp = PIDir::temporary().path() + PIDir::separator + "file" + PIString::fromNumber(randomi());
while (isExists(tp)) {
tp += PIString::fromNumber(randomi() % 10);
}
#else
# else
char template_rc[] = "/tmp/pifile_tmp_XXXXXX";
int fd = mkstemp(template_rc);
if (fd == -1) return false;
::close(fd);
tp = template_rc;
#endif
# endif
return open(tp, mode);
}
@@ -213,9 +213,9 @@ bool PIFile::openDevice() {
bool opened = (PRIVATE->fd != 0);
if (opened) {
fdi = fileno(PRIVATE->fd);
#ifndef WINDOWS
# ifndef WINDOWS
fcntl(fdi, F_SETFL, O_NONBLOCK);
#endif
# endif
if (mode_ == PIIODevice::ReadOnly) {
_fseek_call_(PRIVATE->fd, 0, SEEK_END);
_size = _ftell_call_(PRIVATE->fd);
@@ -307,11 +307,11 @@ bool PIFile::isExists(const PIString & path) {
bool PIFile::remove(const PIString & path) {
#ifdef WINDOWS
# ifdef WINDOWS
if (PIDir::isExists(path))
return RemoveDirectoryA(path.data()) > 0;
else
#endif
# endif
return ::remove(path.data()) == 0;
}
@@ -479,7 +479,7 @@ PIFile::FileInfo PIFile::fileInfo(const PIString & path) {
ret.path = path.replacedAll("\\", PIDir::separator);
PIString n = ret.name();
// piCout << "open" << path;
#ifdef WINDOWS
# ifdef WINDOWS
DWORD attr = GetFileAttributesA((LPCSTR)(path.data()));
if (attr == 0xFFFFFFFF) return ret;
HANDLE hFile = 0;
@@ -511,37 +511,37 @@ PIFile::FileInfo PIFile::fileInfo(const PIString & path) {
ret.time_modification = FILETIME2PIDateTime(fi.ftLastWriteTime);
}
CloseHandle(hFile);
#else
# else
_stat_struct_ fs;
piZeroMemory(fs);
_stat_call_(path.data(), &fs);
int mode = fs.st_mode;
ret.size = fs.st_size;
ret.id_user = fs.st_uid;
ret.id_group = fs.st_gid;
# ifdef ANDROID
int mode = fs.st_mode;
ret.size = fs.st_size;
ret.id_user = fs.st_uid;
ret.id_group = fs.st_gid;
# ifdef ANDROID
ret.time_access = PIDateTime::fromSystemTime(PISystemTime(fs.st_atime, fs.st_atime_nsec));
ret.time_modification = PIDateTime::fromSystemTime(PISystemTime(fs.st_mtime, fs.st_mtime_nsec));
# else
# if defined(QNX) || defined(FREERTOS)
# else
# if defined(QNX) || defined(FREERTOS)
ret.time_access = PIDateTime::fromSecondSinceEpoch(fs.st_atime);
ret.time_modification = PIDateTime::fromSecondSinceEpoch(fs.st_mtime);
# else
# ifdef MAC_OS
# define ATIME st_atimespec
# define MTIME st_ctimespec
# else
# define ATIME st_atim
# define MTIME st_mtim
# endif
# ifdef MAC_OS
# define ATIME st_atimespec
# define MTIME st_ctimespec
# else
# define ATIME st_atim
# define MTIME st_mtim
# endif
ret.time_access = PIDateTime::fromSystemTime(PISystemTime(fs.ATIME.tv_sec, fs.ATIME.tv_nsec));
ret.time_modification = PIDateTime::fromSystemTime(PISystemTime(fs.MTIME.tv_sec, fs.MTIME.tv_nsec));
# endif
# endif
# endif
# ifndef MICRO_PIP
ret.perm_user = FileInfo::Permissions((mode & S_IRUSR) == S_IRUSR, (mode & S_IWUSR) == S_IWUSR, (mode & S_IXUSR) == S_IXUSR);
ret.perm_group = FileInfo::Permissions((mode & S_IRGRP) == S_IRGRP, (mode & S_IWGRP) == S_IWGRP, (mode & S_IXGRP) == S_IXGRP);
ret.perm_other = FileInfo::Permissions((mode & S_IROTH) == S_IROTH, (mode & S_IWOTH) == S_IWOTH, (mode & S_IXOTH) == S_IXOTH);
# ifndef PIP_NO_FILESYSTEM
ret.perm_user = FileInfo::Permissions((mode & S_IRUSR) == S_IRUSR, (mode & S_IWUSR) == S_IWUSR, (mode & S_IXUSR) == S_IXUSR);
ret.perm_group = FileInfo::Permissions((mode & S_IRGRP) == S_IRGRP, (mode & S_IWGRP) == S_IWGRP, (mode & S_IXGRP) == S_IXGRP);
ret.perm_other = FileInfo::Permissions((mode & S_IROTH) == S_IROTH, (mode & S_IWOTH) == S_IWOTH, (mode & S_IXOTH) == S_IXOTH);
piZeroMemory(fs);
_stat_link_(path.data(), &fs);
mode &= ~S_IFLNK;
@@ -551,8 +551,8 @@ PIFile::FileInfo PIFile::fileInfo(const PIString & path) {
if ((mode & S_IFREG) == S_IFREG) ret.flags |= FileInfo::File;
if ((mode & S_IFLNK) == S_IFLNK) ret.flags |= FileInfo::SymbolicLink;
if ((mode & S_IFHDN) == S_IFHDN) ret.flags |= FileInfo::Hidden;
# endif
# endif
#endif
if (n == ".") ret.flags = FileInfo::Dir | FileInfo::Dot;
if (n == "..") ret.flags = FileInfo::Dir | FileInfo::DotDot;
return ret;
@@ -563,7 +563,7 @@ bool PIFile::applyFileInfo(const PIString & path, const PIFile::FileInfo & info)
if (path.isEmpty()) return false;
PIString fp(path);
if (fp.endsWith(PIDir::separator)) fp.pop_back();
#ifdef WINDOWS
# ifdef WINDOWS
DWORD attr = GetFileAttributesA((LPCSTR)(path.data()));
if (attr == 0xFFFFFFFF) return false;
attr &= ~(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
@@ -591,7 +591,7 @@ bool PIFile::applyFileInfo(const PIString & path, const PIFile::FileInfo & info)
return false;
}
CloseHandle(hFile);
#else
# else
int mode(0);
if (info.perm_user.read) mode |= S_IRUSR;
if (info.perm_user.write) mode |= S_IWUSR;
@@ -618,7 +618,7 @@ bool PIFile::applyFileInfo(const PIString & path, const PIFile::FileInfo & info)
if (utimes(fp.data(), tm) != 0) {
piCout << "[PIFile] applyFileInfo: \"utimes\" error:" << errorString();
}
#endif
# endif
return true;
}
+21 -18
View File
@@ -30,6 +30,7 @@
#endif
#include "piliterals.h"
#ifndef PIP_NO_THREADS
//! \class PIGPIO pigpio.h
//! \~english \section PIGPIO_sec0 Synopsis
@@ -74,7 +75,7 @@ PIGPIO::~PIGPIO() {
stop();
waitForFinish(100_ms);
PIMutexLocker ml(mutex);
#ifdef GPIO_SYS_CLASS
# ifdef GPIO_SYS_CLASS
PIVector<int> ids = gpio_.keys();
for (int i = 0; i < ids.size_s(); i++) {
GPIOData & g(gpio_[ids[i]]);
@@ -84,7 +85,7 @@ PIGPIO::~PIGPIO() {
}
}
gpio_.clear();
#endif
# endif
}
@@ -100,7 +101,7 @@ PIString PIGPIO::GPIOName(int gpio_num) {
void PIGPIO::exportGPIO(int gpio_num) {
#ifdef GPIO_SYS_CLASS
# ifdef GPIO_SYS_CLASS
PIString valfile = "/sys/class/gpio/" + GPIOName(gpio_num) + "/value";
int fd = ::open(valfile.dataAscii(), O_RDONLY);
if (fd != -1) {
@@ -120,12 +121,12 @@ void PIGPIO::exportGPIO(int gpio_num) {
piMSleep(1);
}
}
#endif
# endif
}
void PIGPIO::openGPIO(GPIOData & g) {
#ifdef GPIO_SYS_CLASS
# ifdef GPIO_SYS_CLASS
if (g.fd != -1) {
::close(g.fd);
g.fd = -1;
@@ -133,12 +134,12 @@ void PIGPIO::openGPIO(GPIOData & g) {
PIString fp = "/sys/class/gpio/" + g.name + "/value";
g.fd = ::open(fp.dataAscii(), O_RDWR);
// piCoutObj << "initGPIO" << g.num << ":" << fp << g.fd << errorString();
#endif
# endif
}
bool PIGPIO::getPinState(int gpio_num) {
#ifdef GPIO_SYS_CLASS
# ifdef GPIO_SYS_CLASS
GPIOData & g(gpio_[gpio_num]);
char r = 0;
int ret = 0;
@@ -151,7 +152,7 @@ bool PIGPIO::getPinState(int gpio_num) {
}
}
// piCoutObj << "pinState" << gpio_num << ":" << ret << (int)r << errorString();
#endif
# endif
return false;
}
@@ -201,9 +202,9 @@ void PIGPIO::end() {
for (int i = 0; i < ids.size_s(); i++) {
GPIOData & g(gpio_[ids[i]]);
if (g.fd != -1) {
#ifdef GPIO_SYS_CLASS
# ifdef GPIO_SYS_CLASS
::close(g.fd);
#endif
# endif
g.fd = -1;
}
}
@@ -211,7 +212,7 @@ void PIGPIO::end() {
void PIGPIO::initPin(int gpio_num, Direction dir) {
#ifdef GPIO_SYS_CLASS
# ifdef GPIO_SYS_CLASS
PIMutexLocker ml(mutex);
GPIOData & g(gpio_[gpio_num]);
if (g.num == -1) {
@@ -228,12 +229,12 @@ void PIGPIO::initPin(int gpio_num, Direction dir) {
default: break;
}
openGPIO(g);
#endif
# endif
}
void PIGPIO::pinSet(int gpio_num, bool value) {
#ifdef GPIO_SYS_CLASS
# ifdef GPIO_SYS_CLASS
PIMutexLocker ml(mutex);
GPIOData & g(gpio_[gpio_num]);
int ret = 0;
@@ -245,7 +246,7 @@ void PIGPIO::pinSet(int gpio_num, bool value) {
ret = ::write(g.fd, "0", 1);
}
// piCoutObj << "pinSet" << gpio_num << ":" << ret << errorString();
#endif
# endif
}
@@ -267,9 +268,9 @@ void PIGPIO::pinBeginWatch(int gpio_num) {
PIMutexLocker ml(mutex);
GPIOData & g(gpio_[gpio_num]);
if (g.fd != -1) {
#ifdef GPIO_SYS_CLASS
# ifdef GPIO_SYS_CLASS
::close(g.fd);
#endif
# endif
g.fd = -1;
}
watch_state.insert(gpio_num, false);
@@ -304,6 +305,8 @@ void PIGPIO::clearWatch() {
}
#ifdef __GNUC__
# ifdef __GNUC__
// # pragma GCC diagnostic pop
#endif
# endif
#endif // PIP_NO_THREADS
+3 -1
View File
@@ -28,6 +28,7 @@
#include "pithread.h"
#ifndef PIP_NO_THREADS
//! \~\ingroup IO
//! \~\brief
@@ -143,5 +144,6 @@ private:
PIMutex mutex;
};
#endif // PIP_NO_THREADS
#endif // PIDIR_H
#endif // PIGPIO_H
+51 -19
View File
@@ -117,7 +117,9 @@
//!
#ifndef PIP_NO_THREADS
PIMutex PIIODevice::nfp_mutex;
#endif
PIMap<PIString, PIString> PIIODevice::nfp_cache;
@@ -138,6 +140,7 @@ PIIODevice::PIIODevice(const PIString & path, PIIODevice::DeviceMode mode): PIOb
PIIODevice::~PIIODevice() {
destroying = true;
stopAndWait();
(void)destroying;
}
@@ -195,6 +198,7 @@ void PIIODevice::setThreadedReadBufferSize(int new_size) {
}
#ifndef PIP_NO_THREADS
bool PIIODevice::isThreadedRead() const {
return read_thread.isRunning();
}
@@ -216,16 +220,12 @@ void PIIODevice::startThreadedRead(ReadRetFunc func) {
void PIIODevice::stopThreadedRead() {
if (!isThreadedRead()) return;
#ifdef MICRO_PIP
read_thread.stop();
#else
read_thread.stop();
if (!destroying) {
interrupt();
} else {
piCoutObj << "Error: Device is running after destructor!"_tr("PIIODevice");
}
#endif
}
@@ -248,56 +248,80 @@ bool PIIODevice::waitThreadedReadFinished(PISystemTime timeout) {
}
return true;
}
#endif
bool PIIODevice::isThreadedWrite() const {
#ifndef PIP_NO_THREADS
return write_thread.isRunning();
#else
return false;
#endif
}
void PIIODevice::startThreadedWrite() {
#ifndef PIP_NO_THREADS
if (!write_thread.isRunning()) write_thread.startOnce();
#endif
}
void PIIODevice::stopThreadedWrite() {
#ifndef PIP_NO_THREADS
if (!write_thread.isRunning()) return;
write_thread.stop();
#endif
}
void PIIODevice::terminateThreadedWrite() {
#ifndef PIP_NO_THREADS
write_thread.terminate();
#endif
}
bool PIIODevice::waitThreadedWriteFinished(PISystemTime timeout) {
#ifndef PIP_NO_THREADS
return write_thread.waitForFinish(timeout);
#else
(void)timeout;
return true;
#endif
}
void PIIODevice::clearThreadedWriteQueue() {
#ifndef PIP_NO_THREADS
write_thread.lock();
write_queue.clear();
write_thread.unlock();
#endif
}
void PIIODevice::start() {
#ifndef PIP_NO_THREADS
startThreadedRead();
#endif
startThreadedWrite();
}
void PIIODevice::stop() {
#ifndef PIP_NO_THREADS
stopThreadedRead();
#endif
stopThreadedWrite();
}
void PIIODevice::stopAndWait(PISystemTime timeout) {
stop();
#ifndef PIP_NO_THREADS
waitThreadedReadFinished(timeout);
#endif
waitThreadedWriteFinished(timeout);
}
@@ -333,11 +357,10 @@ void PIIODevice::_init() {
setOptions(0);
setReopenEnabled(true);
setReopenTimeout(1_s);
#ifdef MICRO_PIP
#ifdef PIP_NO_THREADS
threaded_read_buffer_size = 512;
#else
threaded_read_buffer_size = 4_KiB;
#endif
read_thread.setName("_S.PIIODev.read");
write_thread.setName("_S.PIIODev.write");
CONNECT(void, &write_thread, started, this, write_func);
@@ -345,9 +368,11 @@ void PIIODevice::_init() {
if (!isOpened()) open();
});
read_thread.setSlot([this](void *) { read_func(); });
#endif // PIP_NO_THREADS
}
#ifndef PIP_NO_THREADS
void PIIODevice::write_func() {
while (!write_thread.isStopping()) {
while (!write_queue.isEmpty()) {
@@ -362,15 +387,6 @@ void PIIODevice::write_func() {
}
}
PIIODevice * PIIODevice::newDeviceByPrefix(const char * prefix) {
if (!prefix) return nullptr;
auto fi = fabrics().value(prefix);
if (fi.fabricator) return fi.fabricator();
return nullptr;
}
void PIIODevice::read_func() {
if (!isReadable()) {
read_thread.stop();
@@ -391,13 +407,20 @@ void PIIODevice::read_func() {
if (read_thread.isStopping()) return;
if (readed_ <= 0) {
piMSleep(threaded_read_timeout_ms);
// cout << readed_ << ", " << errno << ", " << errorString() << endl;
return;
}
// piCoutObj << "readed" << readed_;// << ", " << errno << ", " << errorString();
threadedRead(buffer_tr.data(), readed_);
threadedReadEvent(buffer_tr.data(), readed_);
}
#endif // PIP_NO_THREADS
PIIODevice * PIIODevice::newDeviceByPrefix(const char * prefix) {
if (!prefix) return nullptr;
auto fi = fabrics().value(prefix);
if (fi.fabricator) return fi.fabricator();
return nullptr;
}
PIByteArray PIIODevice::readForTime(PISystemTime timeout) {
@@ -420,6 +443,7 @@ PIByteArray PIIODevice::readForTime(PISystemTime timeout) {
}
#ifndef PIP_NO_THREADS
ullong PIIODevice::writeThreaded(const PIByteArray & data) {
write_thread.lock();
write_queue.enqueue(PIPair<PIByteArray, ullong>(data, tri));
@@ -427,6 +451,7 @@ ullong PIIODevice::writeThreaded(const PIByteArray & data) {
write_thread.unlock();
return tri - 1;
}
#endif
bool PIIODevice::open() {
@@ -543,7 +568,7 @@ void PIIODevice::splitFullPath(PIString fpwm, PIString * full_path, DeviceMode *
if (o == "br"_a || o == "blockr"_a || o == "blockread"_a || o == "blockingread"_a) op |= BlockingRead;
if (o == "bw"_a || o == "blockw"_a || o == "blockwrite"_a || o == "blockingwrite"_a) op |= BlockingWrite;
if (o == "brw"_a || o == "bwr"_a || o == "blockrw"_a || o == "blockwr"_a || o == "blockreadrite"_a ||
o == "blockingreadwrite"_a)
o == "blockingreadwrite"_a)
op |= BlockingRead | BlockingWrite;
}
fpwm.cutRight(fpwm.length() - fpwm.findLast('(')).trim();
@@ -638,15 +663,20 @@ PIIODevice * PIIODevice::createFromVariant(const PIVariantTypes::IODevice & d) {
PIString PIIODevice::normalizeFullPath(const PIString & full_path) {
#ifndef PIP_NO_THREADS
nfp_mutex.lock();
#endif
PIString ret = nfp_cache.value(full_path);
if (!ret.isEmpty()) {
#ifndef PIP_NO_THREADS
nfp_mutex.unlock();
#endif
return ret;
}
#ifndef PIP_NO_THREADS
nfp_mutex.unlock();
#endif
PIIODevice * d = createFromFullPath(full_path);
// piCout << "normalizeFullPath" << d;
if (d == 0) return PIString();
ret = d->constructFullPath();
delete d;
@@ -655,7 +685,9 @@ PIString PIIODevice::normalizeFullPath(const PIString & full_path) {
void PIIODevice::cacheFullPath(const PIString & full_path, const PIIODevice * d) {
#ifndef PIP_NO_THREADS
PIMutexLocker nfp_ml(nfp_mutex);
#endif
nfp_cache[full_path] = d->constructFullPath();
}
+23 -24
View File
@@ -59,26 +59,20 @@ typedef std::function<bool(const uchar *, int, void *)> ReadRetFunc;
#else
# define REGISTER_DEVICE(name) \
STATIC_INITIALIZER_BEGIN \
PIIODevice::registerDevice(name::fullPathPrefixS(), #name, []() -> PIIODevice * { return new name(); }); \
STATIC_INITIALIZER_END
# define REGISTER_DEVICE(name) \
STATIC_INITIALIZER_BEGIN \
PIIODevice::registerDevice(name::fullPathPrefixS(), #name, []() -> PIIODevice * { return new name(); }); \
STATIC_INITIALIZER_END
# define PIIODEVICE(name, prefix) \
PIOBJECT_SUBCLASS(name, PIIODevice) \
PIIODevice * copy() const override { \
return new name(); \
} \
\
public: \
PIConstChars fullPathPrefix() const override { \
return prefix; \
} \
static PIConstChars fullPathPrefixS() { \
return prefix; \
} \
\
private:
# define PIIODEVICE(name, prefix) \
PIOBJECT_SUBCLASS(name, PIIODevice) \
PIIODevice * copy() const override { return new name(); } \
\
public: \
PIConstChars fullPathPrefix() const override { return prefix; } \
static PIConstChars fullPathPrefixS() { return prefix; } \
\
private:
#endif
@@ -248,7 +242,7 @@ public:
//! \~russian Возвращает пользовательские данные, передаваемые в callback потокового чтения.
void * threadedReadData() const { return ret_data_; }
#ifndef PIP_NO_THREADS
//! \~english Returns whether threaded read is running.
//! \~russian Возвращает, запущено ли потоковое чтение.
bool isThreadedRead() const;
@@ -279,6 +273,7 @@ public:
//! \~english Waits until threaded read finishes or "timeout" expires.
//! \~russian Ожидает завершения потокового чтения, но не дольше "timeout".
bool waitThreadedReadFinished(PISystemTime timeout = {});
#endif // PIP_NO_THREADS
//! \~english Returns delay between unsuccessful threaded read attempts in milliseconds.
@@ -367,6 +362,7 @@ public:
PIByteArray readForTime(PISystemTime timeout);
#ifndef PIP_NO_THREADS
//! \~english Queues "data" for threaded write and returns task ID.
//! \~russian Помещает "data" в очередь потоковой записи и возвращает ID задания.
ullong writeThreaded(const void * data, ssize_t max_size) { return writeThreaded(PIByteArray(data, uint(max_size))); }
@@ -374,6 +370,7 @@ public:
//! \~english Queues byte array "data" for threaded write and returns task ID.
//! \~russian Помещает массив байт "data" в очередь потоковой записи и возвращает ID задания.
ullong writeThreaded(const PIByteArray & data);
#endif
//! \~english Configures the device from section "section" of file "config_file".
@@ -611,16 +608,18 @@ private:
static PIMap<PIConstChars, FabricInfo> & fabrics();
PITimeMeasurer tm, reopen_tm;
PIThread read_thread, write_thread;
PIByteArray buffer_in, buffer_tr;
PIQueue<PIPair<PIByteArray, ullong>> write_queue;
PISystemTime reopen_timeout;
ullong tri = 0;
uint threaded_read_buffer_size, threaded_read_timeout_ms = 10;
bool reopen_enabled = true, destroying = false;
static PIMutex nfp_mutex;
static PIMap<PIString, PIString> nfp_cache;
#ifndef PIP_NO_THREADS
PIThread read_thread, write_thread;
PIQueue<PIPair<PIByteArray, ullong>> write_queue;
static PIMutex nfp_mutex;
#endif
};
#endif // PIIODEVICE_H
+20 -16
View File
@@ -23,20 +23,22 @@
#include "pidatatransfer.h"
#include "piliterals_time.h"
#include "pipropertystorage.h"
#include "pitime.h"
#define _PIPEER_MSG_SIZE 4000
#define _PIPEER_MSG_TTL 100
#define _PIPEER_MULTICAST_TTL 4
#define _PIPEER_MULTICAST_IP "232.13.3.12"
#define _PIPEER_LOOPBACK_PORT_S 13313
#define _PIPEER_LOOPBACK_PORT_E (13313 + 32)
#define _PIPEER_MULTICAST_PORT 13360
#define _PIPEER_TCP_PORT _PIPEER_MULTICAST_PORT
#define _PIPEER_BROADCAST_PORT 13361
#define _PIPEER_TRAFFIC_PORT_S 13400
#define _PIPEER_TRAFFIC_PORT_E 14000
#define _PIPEER_PING_TIMEOUT 5.0
#ifndef PIP_NO_SOCKET
# include "pitime.h"
# define _PIPEER_MSG_SIZE 4000
# define _PIPEER_MSG_TTL 100
# define _PIPEER_MULTICAST_TTL 4
# define _PIPEER_MULTICAST_IP "232.13.3.12"
# define _PIPEER_LOOPBACK_PORT_S 13313
# define _PIPEER_LOOPBACK_PORT_E (13313 + 32)
# define _PIPEER_MULTICAST_PORT 13360
# define _PIPEER_TCP_PORT _PIPEER_MULTICAST_PORT
# define _PIPEER_BROADCAST_PORT 13361
# define _PIPEER_TRAFFIC_PORT_S 13400
# define _PIPEER_TRAFFIC_PORT_E 14000
# define _PIPEER_PING_TIMEOUT 5.0
class PIPeer::PeerData: public PIObject {
PIOBJECT_SUBCLASS(PeerData, PIObject);
@@ -893,11 +895,11 @@ void PIPeer::pingNeighbours() {
bool PIPeer::openDevice() {
PIConfig conf(
#ifndef WINDOWS
# ifndef WINDOWS
"/etc/pip.conf"
#else
# else
"pip.conf"
#endif
# endif
,
PIIODevice::ReadOnly);
server_ip = conf.getValue("peer_server_ip", "").toString();
@@ -1176,3 +1178,5 @@ bool PIPeer::hasPeer(const PIString & name) {
if (i.name == name) return true;
return false;
}
#endif // PIP_NO_SOCKET
+3 -2
View File
@@ -34,10 +34,11 @@
//! \~russian Именованный сетевой пир, построенный поверх %PIIODevice.
//! \~\details
//! \~english
//! The class discovers peers, routes packets by peer name and can expose a trusted-peer stream through inherited \a read() and \a write().
//! The class discovers peers, routes packets by peer name and can expose a trusted-peer stream through inherited \a read() и \a write().
//! \~russian
//! Класс обнаруживает пиры, маршрутизирует пакеты по имени пира и может предоставлять поток trusted-peer через унаследованные \a read() и
//! \a write().
#ifndef PIP_NO_SOCKET
class PIP_EXPORT PIPeer: public PIIODevice {
PIIODEVICE(PIPeer, "peer");
@@ -436,6 +437,6 @@ BINARY_STREAM_READ(PIPeer::PeerInfo) {
s >> v.name >> v.addresses >> v.dist >> v.neighbours >> v.cnt >> v.time;
return s;
}
#endif // PIP_NO_SOCKET
#endif // PIPEER_H
+2 -2
View File
@@ -19,7 +19,7 @@
#include "piserial.h"
#ifndef MICRO_PIP
#ifndef PIP_NO_SERIAL
# include "piconfig.h"
# include "pidir.h"
@@ -1321,4 +1321,4 @@ void PISerial::threadedReadBufferSizeChanged() {
# endif
}
#endif // MICRO_PIP
#endif // PIP_NO_SERIAL
+2 -2
View File
@@ -43,11 +43,11 @@ REGISTER_DEVICE(PISPI)
PISPI::PISPI(const PIString & path, uint speed, PIIODevice::DeviceMode mode): PIIODevice(path, mode) {
#ifdef MICRO_PIP
#ifdef PIP_NO_THREADS
setThreadedReadBufferSize(512);
#else
setThreadedReadBufferSize(1024);
#endif
#endif // PIP_NO_THREADS
setPath(path);
setSpeed(speed);
setBits(8);
+32 -3
View File
@@ -27,7 +27,12 @@
const uint PIBaseTransfer::signature = 0x54424950;
PIBaseTransfer::PIBaseTransfer(): crc(standardCRC_16()), diag(false) {
PIBaseTransfer::PIBaseTransfer()
: crc(standardCRC_16())
#ifndef PIP_NO_THREADS
, diag(false)
#endif
{
header.sig = signature;
crc_enabled = true;
header.session_id = 0;
@@ -39,12 +44,14 @@ PIBaseTransfer::PIBaseTransfer(): crc(standardCRC_16()), diag(false) {
send_queue = 0;
send_up = 0;
timeout_ = 10.;
#ifndef PIP_NO_THREADS
diag.setDisconnectTimeout(PISystemTime::fromSeconds(timeout_ / 10.));
diag.setName("PIBaseTransfer");
diag.start(20_Hz);
#endif
packets_count = 10;
#ifdef MICRO_PIP
setPacketSize(512);
#ifdef PIP_EMBEDDED
setPacketSize(1024);
#else
setPacketSize(4096);
#endif
@@ -53,7 +60,9 @@ PIBaseTransfer::PIBaseTransfer(): crc(standardCRC_16()), diag(false) {
PIBaseTransfer::~PIBaseTransfer() {
#ifndef PIP_NO_THREADS
diag.stopAndWait();
#endif
break_ = true;
}
@@ -85,14 +94,18 @@ void PIBaseTransfer::setPause(bool pause_) {
void PIBaseTransfer::setTimeout(double sec) {
timeout_ = sec;
#ifndef PIP_NO_THREADS
diag.setDisconnectTimeout(PISystemTime::fromSeconds(sec));
#endif
}
void PIBaseTransfer::received(PIByteArray data) {
packet_header_size = sizeof(PacketHeader) + customHeader().size();
if (data.size() < sizeof(PacketHeader)) {
#ifndef PIP_NO_THREADS
diag.received(data.size(), false);
#endif
return;
}
PacketHeader h;
@@ -100,10 +113,14 @@ void PIBaseTransfer::received(PIByteArray data) {
PacketType pt = (PacketType)h.type;
if (!h.check_sig()) {
piCoutObj << "invalid packet signature"_tr("PIBaseTransfer");
#ifndef PIP_NO_THREADS
diag.received(data.size(), false);
#endif
return;
} else
#ifndef PIP_NO_THREADS
diag.received(data.size(), true);
#endif
// piCoutObj << "receive" << h.session_id << h.type << h.id;
switch (pt) {
case pt_Unknown: break;
@@ -244,7 +261,9 @@ void PIBaseTransfer::received(PIByteArray data) {
replies.resize(sr.packets + 1);
replies.fill(pt_Unknown);
pm_string.resize(replies.size(), '-');
#ifndef PIP_NO_THREADS
diag.reset();
#endif
// piCoutObj << "receiveStarted()";
is_receiving = true;
break_ = false;
@@ -291,7 +310,9 @@ bool PIBaseTransfer::send_process() {
mutex_session.lock();
packet_header_size = sizeof(PacketHeader) + customHeader().size();
break_ = false;
#ifndef PIP_NO_THREADS
diag.reset();
#endif
sendStarted();
is_sending = true;
int session_size = session.size();
@@ -339,7 +360,9 @@ bool PIBaseTransfer::send_process() {
}
stm.reset();
ba = build_packet(i);
#ifndef PIP_NO_THREADS
diag.sended(ba.size_s());
#endif
sendRequest(ba);
pm_string[i + 1] = '+';
mutex_send.lock();
@@ -392,7 +415,9 @@ bool PIBaseTransfer::send_process() {
continue;
}
ba = build_packet(chk - 1);
#ifndef PIP_NO_THREADS
diag.sended(ba.size_s());
#endif
sendRequest(ba);
pm_string[chk] = '+';
mutex_send.lock();
@@ -497,7 +522,9 @@ void PIBaseTransfer::sendReply(PacketType reply) {
header.type = reply;
PIByteArray ba;
ba << header;
#ifndef PIP_NO_THREADS
if (is_sending || is_receiving) diag.sended(ba.size_s());
#endif
sendRequest(ba);
}
@@ -516,7 +543,9 @@ bool PIBaseTransfer::getStartRequest() {
state_string = "send request";
PITimeMeasurer tm;
while (tm.elapsed_s() < timeout_) {
#ifndef PIP_NO_THREADS
diag.sended(ba.size_s());
#endif
sendRequest(ba);
if (break_) return false;
// piCoutObj << replies[0];
+4
View File
@@ -159,12 +159,14 @@ public:
//! \~russian Возвращает число байтов, уже обработанных в текущей сессии.
llong bytesCur() const { return bytes_cur; }
#ifndef PIP_NO_THREADS
//! \~english Get diagnostics object
//! \~russian Получить объект диагностики
//! \~\return
//! \~english Diagnostic object reference
//! \~russian Ссылка на объект диагностики
const PIDiagnostics & diagnostic() { return diag; }
#endif
//! \~english Returns the packet signature constant used by the protocol.
//! \~russian Возвращает константу сигнатуры пакета, используемую протоколом.
@@ -344,7 +346,9 @@ private:
CRC_16 crc;
int send_queue;
int send_up;
#ifndef PIP_NO_THREADS
PIDiagnostics diag;
#endif
PIMutex mutex_session;
PIMutex mutex_send;
PIMutex mutex_header;
+2
View File
@@ -34,6 +34,7 @@
//! \~\brief
//! \~english Multi-channel sender and receiver over multicast, broadcast and loopback endpoints.
//! \~russian Многоканальный отправитель и приемник через multicast-, broadcast- и loopback-конечные точки.
#ifndef PIP_NO_SOCKET
class PIP_IO_UTILS_EXPORT PIBroadcast
: public PIThread
, public PIEthUtilBase {
@@ -182,5 +183,6 @@ private:
int lo_pcnt;
bool _started, _send_only, _reinit;
};
#endif // PIP_NO_SOCKET
#endif // PIBROADCAST_H
+5 -1
View File
@@ -23,7 +23,9 @@
#include "piiostream.h"
#include "piliterals_time.h"
#include "pitime.h"
#include "pitranslator.h"
#ifndef PIP_NO_THREADS
# include "pitranslator.h"
/** \class PIConnection
* \brief Complex Input/Output point
@@ -1294,3 +1296,5 @@ __DevicePoolContainer__::__DevicePoolContainer__() {
inited_ = true;
__device_pool__ = new PIConnection::DevicePool();
}
#endif // PIP_NO_THREADS
+16
View File
@@ -379,6 +379,7 @@ public:
bool isEmpty() const { return device_modes.isEmpty(); }
#ifndef PIP_NO_THREADS
//! \~english Returns diagnostics object for device or filter "full_path_name".
//! \~russian Возвращает объект диагностики для устройства или фильтра "full_path_name".
PIDiagnostics * diagnostic(const PIString & full_path_name) const;
@@ -386,6 +387,7 @@ public:
//! \~english Returns diagnostics object associated with device or filter "dev".
//! \~russian Возвращает объект диагностики, связанный с устройством или фильтром "dev".
PIDiagnostics * diagnostic(const PIIODevice * dev) const { return diags_.value(const_cast<PIIODevice *>(dev), 0); }
#endif
//! \~english Writes "data" to device resolved by full path "full_path".
//! \~russian Записывает "data" в устройство, найденное по полному пути "full_path".
@@ -415,6 +417,7 @@ public:
//! \~russian Возвращает, работает ли общий пул устройств в режиме имитации.
static bool isFakeMode();
#ifndef PIP_NO_THREADS
class PIP_EXPORT DevicePool: public PIThread {
PIOBJECT_SUBCLASS(DevicePool, PIThread);
friend void __DevicePool_threadReadDP(void * ddp);
@@ -456,6 +459,7 @@ public:
PIMap<PIString, DeviceData *> devices;
bool fake;
};
#endif // PIP_NO_THREADS
//! \events
@@ -471,10 +475,12 @@ public:
//! \~russian Генерируется, когда фильтр "from" выдает пакет.
EVENT2(packetReceivedEvent, const PIString &, from, const PIByteArray &, data);
#ifndef PIP_NO_THREADS
//! \fn void qualityChanged(const PIIODevice * device, PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality)
//! \~english Emitted when diagnostics quality of "device" changes.
//! \~russian Генерируется при изменении качества диагностики устройства "device".
EVENT3(qualityChanged, const PIIODevice *, dev, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality);
#endif
//! \}
@@ -496,7 +502,9 @@ private:
void rawReceived(PIIODevice * dev, const PIString & from, const PIByteArray & data);
void unboundExtractor(PIPacketExtractor * pe);
EVENT_HANDLER2(void, packetExtractorReceived, const uchar *, data, int, size);
#ifndef PIP_NO_THREADS
EVENT_HANDLER2(void, diagQualityChanged, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality);
#endif
PIString devPath(const PIIODevice * d) const;
PIString devFPath(const PIIODevice * d) const;
@@ -509,6 +517,7 @@ private:
PIVector<PIIODevice *> devices;
};
#ifndef PIP_NO_THREADS
class PIP_EXPORT Sender: public PITimer {
PIOBJECT_SUBCLASS(Sender, PIObject);
@@ -521,18 +530,24 @@ private:
PISystemTime int_;
void tick(int) override;
};
#endif
PIMap<PIString, Extractor *> extractors;
#ifndef PIP_NO_THREADS
PIMap<PIString, Sender *> senders;
#endif
PIMap<PIString, PIIODevice *> device_names;
PIMap<PIIODevice *, PIIODevice::DeviceMode> device_modes;
PIMap<PIIODevice *, PIVector<PIPacketExtractor *>> bounded_extractors;
PIMap<PIIODevice *, PIVector<PIIODevice *>> channels_;
#ifndef PIP_NO_THREADS
PIMap<PIIODevice *, PIDiagnostics *> diags_;
#endif
static PIVector<PIConnection *> _connections;
};
#ifndef PIP_NO_THREADS
void __DevicePool_threadReadDP(void * ddp);
extern PIP_EXPORT PIConnection::DevicePool * __device_pool__;
@@ -544,6 +559,7 @@ public:
};
static __DevicePoolContainer__ __device_pool_container__;
#endif // PIP_NO_THREADS
#endif // PICONNECTION_H
+6 -2
View File
@@ -19,8 +19,10 @@
#include "pidiagnostics.h"
#include "piliterals_time.h"
#include "pitranslator.h"
#ifndef PIP_NO_THREADS
# include "piliterals_time.h"
# include "pitranslator.h"
/** \class PIDiagnostics
@@ -250,3 +252,5 @@ void PIDiagnostics::changeDisconnectTimeout(PISystemTime disct) {
// piCoutObj << hist_size << disconn_ << interval();
mutex_state.unlock();
}
#endif // PIP_NO_THREADS
+3 -1
View File
@@ -29,6 +29,7 @@
#include "pitimer.h"
#ifndef PIP_NO_THREADS
//! \~\ingroup IO-Utils
//! \brief
//! \~english Connection diagnostics for packet frequency, throughput and receive quality
@@ -56,7 +57,7 @@ public:
enum Quality {
Unknown = 1 /** \~english No receive history yet \~russian История приема еще отсутствует */,
Failure = 2 /** \~english No correct packets in the recent window \~russian В недавнем окне нет корректных пакетов */,
Bad = 3 /** \~english Correct packets are at most 20 percent \~russian Корректных пакетов не более 20 процентов */,
Bad = 3 /** \~english Correct packets are at most 20 percent \~russian Корректных пакетов не более 20 процентов */,
Average =
4 /** \~english Correct packets are above 20 and up to 80 percent \~russian Корректных пакетов больше 20 и до 80 процентов */
,
@@ -235,5 +236,6 @@ inline bool operator!=(const PIDiagnostics::Entry & f, const PIDiagnostics::Entr
inline bool operator<(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s) {
return f.bytes_ok < s.bytes_ok;
}
#endif // PIP_NO_THREADS
#endif // PIDIAGNOSTICS_H
+2
View File
@@ -24,6 +24,7 @@
#ifndef PIETHUTILBASE_H
#define PIETHUTILBASE_H
#ifndef PIP_NO_SOCKET
#include "pibytearray.h"
#include "pip_io_utils_export.h"
@@ -96,4 +97,5 @@ private:
bool _crypt;
};
#endif // PIP_NO_SOCKET
#endif // PIETHUTILBASE_H
+3
View File
@@ -19,6 +19,7 @@
#include "pifiletransfer.h"
#ifndef PIP_NO_FILESYSTEM
const char PIFileTransfer::sign[] = {'P', 'F', 'T'};
PIFileTransfer::PIFileTransfer() {
@@ -339,3 +340,5 @@ void PIFileTransfer::send_finished(bool ok) {
work_file.close();
}
}
#endif // PIP_NO_FILESYSTEM
+6 -3
View File
@@ -31,7 +31,8 @@
#include "pibasetransfer.h"
#include "pidir.h"
#define __PIFILETRANSFER_VERSION 2
#ifndef PIP_NO_FILESYSTEM
# define __PIFILETRANSFER_VERSION 2
//! \~\ingroup IO-Utils
@@ -70,7 +71,7 @@ public:
PIString dest_path;
};
#pragma pack(push, 1)
# pragma pack(push, 1)
//! \~english Custom packet header used by the file-transfer protocol.
//! \~russian Пользовательский заголовок пакета, используемый протоколом передачи файлов.
@@ -104,7 +105,7 @@ public:
return true;
}
};
#pragma pack(pop)
# pragma pack(pop)
//! \~english Sends one file-system entry identified by "file".
@@ -262,4 +263,6 @@ inline PICout operator<<(PICout s, const PIFileTransfer::PFTFileInfo & v) {
s.restoreControls();
return s;
}
#endif // PIP_NO_FILESYSTEM
#endif // PIFILETRANSFER_H
+3
View File
@@ -24,6 +24,7 @@
#ifndef pipackedtcp_H
#define pipackedtcp_H
#ifndef PIP_NO_SOCKET
#include "piiodevice.h"
#include "pinetworkaddress.h"
@@ -122,4 +123,6 @@ private:
REGISTER_DEVICE(PIPackedTCP)
#endif // PIP_NO_SOCKET
#endif
+2 -2
View File
@@ -98,8 +98,8 @@ void PIPacketExtractor::construct() {
func_payload = nullptr;
setPayloadSize(0);
setTimeout(100_ms);
#ifdef MICRO_PIP
setThreadedReadBufferSize(512);
#ifdef PIP_EMBEDDED
setThreadedReadBufferSize(16_KiB);
#else
setThreadedReadBufferSize(64_KiB);
#endif
+2
View File
@@ -24,6 +24,7 @@
#ifndef PISTREAMPACKER_H
#define PISTREAMPACKER_H
#ifndef PIP_NO_SOCKET
#include "piethutilbase.h"
#include "piobject.h"
@@ -200,4 +201,5 @@ private:
mutable PIMutex prog_s_mutex, prog_r_mutex;
};
#endif // PIP_NO_SOCKET
#endif // PISTREAMPACKER_H
+2 -2
View File
@@ -19,7 +19,7 @@
#include "pifft.h"
#ifndef MICRO_PIP
#ifndef PIP_NO_FFT
PIFFT_double::PIFFT_double() {}
@@ -1961,4 +1961,4 @@ void PIFFT_float::ftbase_ffttwcalc(PIVector<float> * a, int aoffset, int n1, int
}
}
#endif // MICRO_PIP
#endif // PIP_NO_FFT
+13 -13
View File
@@ -59,7 +59,7 @@
#include "pimathcomplex.h"
#ifndef MICRO_PIP
#ifndef PIP_NO_FFT
# include "pip_fftw_export.h"
@@ -225,17 +225,17 @@ typedef PIFFT_float PIFFTf;
# ifndef CC_VC
# define _PIFFTW_H(type) \
class PIP_FFTW_EXPORT _PIFFTW_P_##type##_ { \
public: \
_PIFFTW_P_##type##_(); \
~_PIFFTW_P_##type##_(); \
const PIVector<complex<type>> & calcFFT(const PIVector<complex<type>> & in); \
const PIVector<complex<type>> & calcFFTR(const PIVector<type> & in); \
const PIVector<complex<type>> & calcFFTI(const PIVector<complex<type>> & in); \
void preparePlan(int size, int op); \
void * impl; \
};
# define _PIFFTW_H(type) \
class PIP_FFTW_EXPORT _PIFFTW_P_##type##_ { \
public: \
_PIFFTW_P_##type##_(); \
~_PIFFTW_P_##type##_(); \
const PIVector<complex<type>> & calcFFT(const PIVector<complex<type>> & in); \
const PIVector<complex<type>> & calcFFTR(const PIVector<type> & in); \
const PIVector<complex<type>> & calcFFTI(const PIVector<complex<type>> & in); \
void preparePlan(int size, int op); \
void * impl; \
};
_PIFFTW_H(float)
_PIFFTW_H(double)
_PIFFTW_H(ldouble)
@@ -384,6 +384,6 @@ typedef PIFFTW<ldouble> PIFFTWld;
# endif
#endif // MICRO_PIP
#endif // PIP_NO_FFT
#endif // PIFFT_H
+33 -13
View File
@@ -4,27 +4,28 @@
//! \~english
//! \~russian
/*
PIP - Platform Independent Primitives
MQTT common types
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
MQTT common types
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef pimqtttypes_h
#define pimqtttypes_h
#include "pibinarystream.h"
#include "pip_export.h"
#include "pistringlist.h"
@@ -159,7 +160,26 @@ public:
//! \~russian Возвращает ID сообщения.
MessageMutable & setID(int id);
};
template<typename P>
inline PIBinaryStream<P> & operator<<(PIBinaryStream<P> & s, const MessageConst & v) {
s << v.topic() << v.pathArguments() << v.payload() << v.properties() << static_cast<int>(v.qos()) << v.ID() << v.isDuplicate();
return s;
}
template<typename P>
inline PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, MessageMutable & v) {
PIString topic;
PIMap<PIString, PIString> path_args;
PIByteArray payload;
PIMap<int, PIString> props;
int qos_val, msg_id;
bool is_dup;
s >> topic >> path_args >> payload >> props >> qos_val >> msg_id >> is_dup;
v.setTopic(topic).setPayload(payload).setQos(static_cast<QoS>(qos_val)).setID(msg_id).setDuplicate(is_dup);
v.pathArguments() = path_args;
v.properties() = props;
return s;
}
}; // namespace PIMQTT
+10 -15
View File
@@ -74,12 +74,6 @@
//! \~russian Определяется для целевых сборок FreeBSD.
# define FREE_BSD
//! \~\ingroup Core
//! \~\brief
//! \~english Defined for reduced embedded PIP builds.
//! \~russian Определяется для облегченных встраиваемых сборок PIP.
# define MICRO_PIP
//! \~\ingroup Core
//! \~\brief
//! \~english Defined when the target architecture is 32-bit.
@@ -153,23 +147,24 @@
#ifdef PIP_FREERTOS
# define FREERTOS
#endif
#ifdef MICRO_PIP
# ifndef FREERTOS
# define PIP_NO_THREADS
# endif
# ifndef LWIP
# define PIP_NO_SOCKET
# endif
#ifdef PICO_SDK
# define PISERIAL_NO_PINS
#endif
#ifdef FREERTOS
# ifndef PISERIAL_NO_PINS
# define PISERIAL_NO_PINS
# endif
#endif
#ifndef WINDOWS
# ifndef QNX
# ifndef FREE_BSD
# ifndef MAC_OS
# ifndef ANDROID
# ifndef BLACKBERRY
# ifndef MICRO_PIP
# define LINUX
# ifndef FREERTOS
# ifndef PICO_SDK
# define LINUX
# endif
# endif
# endif
# endif
@@ -43,11 +43,15 @@ PIString mask(const PIString & str) {
}
PIString overrideFile(PIString path) {
#ifndef PIP_NO_FILESYSTEM
if (path.isEmpty()) return {};
PIFile::FileInfo fi(path);
auto ext = fi.extension();
path.insert(path.size_s() - ext.size_s() - (ext.isEmpty() ? 0 : 1), ".override");
return path;
#else
return path;
#endif
}
@@ -138,7 +142,9 @@ PIValueTree PIValueTreeConversions::fromText(PIIODevice * device) {
PIMap<PIString, PIString> substitutions;
if (!device) return ret;
PIString base_path;
#ifndef PIP_NO_FILESYSTEM
if (device->isTypeOf<PIFile>()) base_path = PIFile::FileInfo(device->path()).dir().replaceAll('\\', '/');
#endif
PIIOTextStream ts(device);
PIString line, comm;
PIVariant value;
@@ -211,10 +217,12 @@ PIValueTree PIValueTreeConversions::fromText(PIIODevice * device) {
line.cutLeft(1).trim();
if (path.front() == "include") {
PIString include = line.trimmed();
#ifndef PIP_NO_FILESYSTEM
if (!PIFile::FileInfo(include).isAbsolute()) {
include = base_path + "/" + include.replaceAll('\\', '/');
include.replaceAll("//", '/');
}
#endif
PIValueTree inc_vt = PIValueTreeConversions::fromTextFile(include);
inc_vt.forEachRecursive(
[&substitutions](const PIValueTree & v, const PIString & fn) { substitutions[fn] = v.value().toString(); });
@@ -345,6 +353,9 @@ PIValueTree PIValueTreeConversions::fromText(const PIString & str) {
PIValueTree PIValueTreeConversions::fromJSONFile(const PIString & path) {
#ifdef PIP_NO_FILESYSTEM
return PIValueTree();
#else
auto ret = PIValueTreeConversions::fromJSON(PIJSON::fromJSON(PIString::fromUTF8(PIFile::readAll(path))));
auto ofp = overrideFile(path);
if (PIFile::isExists(ofp)) {
@@ -352,10 +363,14 @@ PIValueTree PIValueTreeConversions::fromJSONFile(const PIString & path) {
ret.merge(override_vt);
}
return ret;
#endif
}
PIValueTree PIValueTreeConversions::fromTextFile(const PIString & path) {
#ifdef PIP_NO_FILESYSTEM
return PIValueTree();
#else
PIFile f(path, PIIODevice::ReadOnly);
auto ret = PIValueTreeConversions::fromText(&f);
auto ofp = overrideFile(path);
@@ -365,18 +380,27 @@ PIValueTree PIValueTreeConversions::fromTextFile(const PIString & path) {
ret.merge(override_vt);
}
return ret;
#endif
}
bool PIValueTreeConversions::toJSONFile(const PIString & path, const PIValueTree & root, Options options) {
#ifdef PIP_NO_FILESYSTEM
return false;
#else
auto d = toJSON(root, options).toJSON(PIJSON::Tree).toUTF8();
int written = PIFile::writeAll(path, d);
return written == d.size_s();
#endif
}
bool PIValueTreeConversions::toTextFile(const PIString & path, const PIValueTree & root, Options options) {
#ifdef PIP_NO_FILESYSTEM
return false;
#else
auto d = toText(root, options).toUTF8();
int written = PIFile::writeAll(path, d);
return written == d.size_s();
#endif
}
@@ -1,20 +1,20 @@
/*
PIP - Platform Independent Primitives
State machine
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
PIP - Platform Independent Primitives
State machine
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pistatemachine_transition.h"
@@ -99,24 +99,32 @@ void PITransitionBase::trigger() {
PITransitionTimeout::PITransitionTimeout(PIStateBase * source, PIStateBase * target, PISystemTime timeout)
: PITransitionBase(source, target, 0) {
#ifndef PIP_NO_THREADS
timer.setInterval(timeout);
timer.setSlot([this] {
trigger();
timer.stop();
});
#endif
}
PITransitionTimeout::~PITransitionTimeout() {
#ifndef PIP_NO_THREADS
timer.stopAndWait();
#endif
}
void PITransitionTimeout::enabled() {
#ifndef PIP_NO_THREADS
timer.start();
#endif
}
void PITransitionTimeout::disabled() {
#ifndef PIP_NO_THREADS
timer.stop();
#endif
}
@@ -5,8 +5,8 @@
//! \~russian Объявляет переходы, используемые в PIStateMachine
/*
PIP - Platform Independent Primitives
State machine transition
Ivan Pelipenko peri4ko@yandex.ru
State machine transition
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
@@ -142,7 +142,9 @@ private:
void enabled() override;
void disabled() override;
#ifndef PIP_NO_THREADS
PITimer timer;
#endif
};
#endif
+74 -70
View File
@@ -2,27 +2,29 @@
#include "piliterals_string.h"
#include "piliterals_time.h"
#ifndef WINDOWS
# include "pidir.h"
# include "pifile.h"
# include "piiostream.h"
# ifdef LINUX
# include <fcntl.h>
# include <linux/input-event-codes.h>
# include <linux/input.h>
# include <sys/ioctl.h>
# include <sys/time.h>
# include <unistd.h>
# else
#ifndef PIP_NO_THREADS
# ifndef WINDOWS
# include "pidir.h"
# include "pifile.h"
# include "piiostream.h"
# ifdef LINUX
# include <fcntl.h>
# include <linux/input-event-codes.h>
# include <linux/input.h>
# include <sys/ioctl.h>
# include <sys/time.h>
# include <unistd.h>
# else
// Stubs for embedded/non-Linux builds
# define EV_SYN 0
# define EV_KEY 1
# define EV_REL 2
# define EV_ABS 3
# define EVIOCGABS(_v) 0
# endif
#else
# define EV_SYN 0
# define EV_KEY 1
# define EV_REL 2
# define EV_ABS 3
# define EVIOCGABS(_v) 0
# endif
# else
// clang-format off
# undef _WIN32_WINNT
# define _WIN32_WINNT 0x0600
@@ -32,7 +34,7 @@ extern "C" {
# include <hidsdi.h>
}
// clang-format on
#endif
# endif
bool PIHIDeviceInfo::match(const PIString & str) const {
@@ -79,14 +81,14 @@ PICout operator<<(PICout s, const PIHIDeviceInfo & v) {
PRIVATE_DEFINITION_START(PIHIDevice)
#ifndef WINDOWS
# ifndef WINDOWS
PIFile file;
bool is_js = false;
#else
# else
PIByteArray buffer;
HANDLE deviceHandle = nullptr;
PHIDP_PREPARSED_DATA preparsed = nullptr;
#endif
# endif
PRIVATE_DEFINITION_END(PIHIDevice)
@@ -95,11 +97,11 @@ PIHIDevice::~PIHIDevice() {
}
bool PIHIDevice::isOpened() const {
#ifndef WINDOWS
# ifndef WINDOWS
return PRIVATE->file.isOpened();
#else
# else
return PRIVATE->deviceHandle;
#endif
# endif
}
@@ -110,21 +112,21 @@ bool PIHIDevice::open(const PIHIDeviceInfo & device) {
di = device;
di.prepare();
if (device.isNull()) return false;
#ifndef WINDOWS
# ifndef WINDOWS
if (!PRIVATE->file.open(di.path, PIIODevice::ReadOnly)) {
piCout << "PIHIDevice::open" << di.path << "error:" << errorString();
return false;
}
PRIVATE->is_js = PIFile::FileInfo(di.path).name().startsWith("js"_a);
return true;
#else
# else
PRIVATE->deviceHandle = CreateFileA(di.path.dataAscii(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
OPEN_EXISTING,
0,
nullptr);
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
OPEN_EXISTING,
0,
nullptr);
if (PRIVATE->deviceHandle == INVALID_HANDLE_VALUE) {
piCoutObj << "PIHIDevice::open" << di.path << "error:" << errorString();
PRIVATE->deviceHandle = nullptr;
@@ -136,7 +138,7 @@ bool PIHIDevice::open(const PIHIDeviceInfo & device) {
return false;
}
return true;
#endif
# endif
}
@@ -147,9 +149,9 @@ bool PIHIDevice::open() {
void PIHIDevice::close() {
stop();
#ifndef WINDOWS
# ifndef WINDOWS
PRIVATE->file.close();
#else
# else
if (PRIVATE->deviceHandle) {
CloseHandle(PRIVATE->deviceHandle);
PRIVATE->deviceHandle = nullptr;
@@ -158,34 +160,34 @@ void PIHIDevice::close() {
HidD_FreePreparsedData(PRIVATE->preparsed);
PRIVATE->preparsed = nullptr;
}
#endif
# endif
}
void PIHIDevice::start() {
if (!isOpened()) return;
PIThread::start(200_Hz);
#ifndef WINDOWS
#else
#endif
# ifndef WINDOWS
# else
# endif
}
void PIHIDevice::stop() {
PIThread::stop();
#ifdef WINDOWS
# ifdef WINDOWS
if (PRIVATE->deviceHandle) {
CancelIoEx(PRIVATE->deviceHandle, nullptr);
}
#endif
# endif
if (!waitForFinish(1000_ms)) terminate();
}
void PIHIDevice::run() {
Event e;
#ifndef WINDOWS
# pragma pack(push, 1)
# ifndef WINDOWS
# pragma pack(push, 1)
struct input_event {
struct timeval time;
ushort type;
@@ -198,7 +200,7 @@ void PIHIDevice::run() {
uchar type; /* event type */
uchar number; /* axis/button number */
};
# pragma pack(pop)
# pragma pack(pop)
if (PRIVATE->is_js) {
js_event ie;
while (PRIVATE->file.read(&ie, sizeof(ie)) == sizeof(ie)) {
@@ -253,7 +255,7 @@ void PIHIDevice::run() {
if (!ok) continue;
}
}
#else
# else
PRIVATE->buffer.resize(di.input_report_size).fill(0);
DWORD readed = 0;
// piCout << "read" << PRIVATE->deviceHandle << PRIVATE->buffer.size();
@@ -293,7 +295,7 @@ void PIHIDevice::run() {
continue;
}
}
#endif
# endif
auto ait = cur_axes.makeIterator();
e.type = Event::tAxisMove;
@@ -333,7 +335,7 @@ double PIHIDevice::procDeadZone(double in) {
PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
PIVector<PIHIDeviceInfo> ret;
#ifndef WINDOWS
# ifndef WINDOWS
auto readFile = [](const PIString & path) {
auto ba = PIFile::readAll(path);
@@ -379,11 +381,11 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
}
/*bool dev_found = false;
for (const auto & d: devs) {
if (d.startsWith("js"_a)) {
dev.path = "/dev/input/"_a + d;
dev_found = true;
break;
}
if (d.startsWith("js"_a)) {
dev.path = "/dev/input/"_a + d;
dev_found = true;
break;
}
}
if (!dev_found) {*/
// search for event<N> dir
@@ -408,7 +410,7 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
ullong bits = readFile(hd_i.path + file).toULLong(16);
// piCout<< PICoutManipulators::Bin << abs;
if (bits > 0) {
#ifdef LINUX
# ifdef LINUX
int fd = ::open(dev.path.dataAscii(), O_RDONLY);
if (fd < 0) {
// piCout << "Warning: can`t open" << dev.path << errorString();
@@ -433,7 +435,7 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
}
}
if (fd >= 0) ::close(fd);
#else
# else
// Stub implementation for non-Linux builds
PIHIDeviceInfo::AxisInfo ai;
ai.is_relative = is_relative;
@@ -445,7 +447,7 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
ret << ai;
}
}
#endif
# endif
}
return ret;
};
@@ -496,7 +498,7 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
}
}
#else
# else
GUID guid;
HidD_GetHidGuid(&guid);
@@ -518,23 +520,23 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
PIScopeExitCall exit_call([&deviceInterfaceDetailData]() { delete[] reinterpret_cast<BYTE *>(deviceInterfaceDetailData); });
deviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet,
&deviceInterfaceData,
deviceInterfaceDetailData,
requiredSize,
nullptr,
nullptr)) {
&deviceInterfaceData,
deviceInterfaceDetailData,
requiredSize,
nullptr,
nullptr)) {
piCout << "SetupDiGetDeviceInterfaceDetail error:" << errorString();
continue;
}
if (try_open) {
auto test_f = CreateFileA(deviceInterfaceDetailData->DevicePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
OPEN_EXISTING,
0,
nullptr);
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
OPEN_EXISTING,
0,
nullptr);
if (test_f == INVALID_HANDLE_VALUE) continue;
CloseHandle(test_f);
}
@@ -657,7 +659,7 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
SetupDiDestroyDeviceInfoList(deviceInfoSet);
#endif
# endif
return ret;
}
@@ -671,3 +673,5 @@ PIHIDeviceInfo PIHIDevice::findDevice(const PIString & name) {
}
return PIHIDeviceInfo();
}
#endif // PIP_NO_THREADS
+3 -1
View File
@@ -169,6 +169,7 @@ PIP_EXPORT PICout operator<<(PICout s, const PIHIDeviceInfo & v);
//! \~english Provides access to HID (Human Interface Device) devices such as game controllers, joysticks, and other input devices.
//! \~russian Предоставляет доступ к HID (Human Interface Device) устройствам, таким как геймконтроллеры, джойстики и другие устройства
//! ввода.
#ifndef PIP_NO_THREADS
class PIP_EXPORT PIHIDevice: public PIThread {
PIOBJECT_SUBCLASS(PIHIDevice, PIThread)
@@ -188,7 +189,7 @@ public:
tNone /** \~english Empty event \~russian Пустое событие */,
tButton /** \~english Button state change \~russian Изменение состояния кнопки */,
tAxisMove /** \~english Axis value change or relative axis delta \~russian Изменение значения оси или дельта относительной оси
*/
*/
,
};
@@ -270,6 +271,7 @@ private:
PIMap<int, int> prev_buttons, cur_buttons;
float dead_zone = 0.f;
};
#endif // PIP_NO_THREADS
#endif
+2 -2
View File
@@ -17,7 +17,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MICRO_PIP
#ifndef PIP_NO_DYNLIB
# include "pilibrary.h"
@@ -233,4 +233,4 @@ void PILibrary::getLastError() {
# endif
}
#endif // MICRO_PIP
#endif // PIP_NO_DYNLIB
+2 -2
View File
@@ -26,7 +26,7 @@
#ifndef PILIBRARY_H
#define PILIBRARY_H
#ifndef MICRO_PIP
#ifndef PIP_NO_DYNLIB
# include "pistring.h"
@@ -82,5 +82,5 @@ private:
PIString libpath, liberror;
};
#endif // MICRO_PIP
#endif // PIP_NO_DYNLIB
#endif // PILIBRARY_H
+2 -2
View File
@@ -17,7 +17,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MICRO_PIP
#ifndef PIP_NO_DYNLIB
# include "piplugin.h"
@@ -493,4 +493,4 @@ PIString PIPluginLoader::libExtension() {
}
#endif // MICRO_PIP
#endif // PIP_NO_DYNLIB
+21 -23
View File
@@ -28,7 +28,7 @@
#ifndef PIPLUGIN_H
#define PIPLUGIN_H
#ifndef MICRO_PIP
#ifndef PIP_NO_DYNLIB
# include "pilibrary.h"
# include "pistringlist.h"
@@ -96,30 +96,28 @@
# define __PIP_PLUGIN_STATIC_MERGE_FUNC__ pip_merge_static
# define __PIP_PLUGIN_LOADER_VERSION__ 2
# define PIP_PLUGIN_SET_USER_VERSION(v) \
STATIC_INITIALIZER_BEGIN \
PIPluginInfo * pi = PIPluginInfoStorage::instance()->currentInfo(); \
if (pi) pi->setUserVersion(v); \
STATIC_INITIALIZER_END
# define PIP_PLUGIN_SET_USER_VERSION(v) \
STATIC_INITIALIZER_BEGIN \
PIPluginInfo * pi = PIPluginInfoStorage::instance()->currentInfo(); \
if (pi) pi->setUserVersion(v); \
STATIC_INITIALIZER_END
# define PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr) \
STATIC_INITIALIZER_BEGIN \
PIPluginInfo * pi = PIPluginInfoStorage::instance()->currentInfo(); \
if (pi) pi->setStaticSection(type, ptr); \
STATIC_INITIALIZER_END
# define PIP_PLUGIN_ADD_STATIC_SECTION(type, ptr) \
STATIC_INITIALIZER_BEGIN \
PIPluginInfo * pi = PIPluginInfoStorage::instance()->currentInfo(); \
if (pi) pi->setStaticSection(type, ptr); \
STATIC_INITIALIZER_END
# define PIP_PLUGIN \
extern "C" { \
PIP_PLUGIN_EXPORT int __PIP_PLUGIN_LOADER_VERSION_FUNC__() { \
return __PIP_PLUGIN_LOADER_VERSION__; \
} \
}
# define PIP_PLUGIN \
extern "C" { \
PIP_PLUGIN_EXPORT int __PIP_PLUGIN_LOADER_VERSION_FUNC__() { return __PIP_PLUGIN_LOADER_VERSION__; } \
}
# define PIP_PLUGIN_STATIC_SECTION_MERGE \
extern "C" { \
PIP_PLUGIN_EXPORT void __PIP_PLUGIN_STATIC_MERGE_FUNC__(int type, void * from, void * to); \
} \
void __PIP_PLUGIN_STATIC_MERGE_FUNC__(int type, void * from, void * to)
# define PIP_PLUGIN_STATIC_SECTION_MERGE \
extern "C" { \
PIP_PLUGIN_EXPORT void __PIP_PLUGIN_STATIC_MERGE_FUNC__(int type, void * from, void * to); \
} \
void __PIP_PLUGIN_STATIC_MERGE_FUNC__(int type, void * from, void * to)
# endif
@@ -300,5 +298,5 @@ private:
};
#endif // MICRO_PIP
#endif // PIP_NO_DYNLIB
#endif // PIPLUGIN_H
+2 -2
View File
@@ -18,7 +18,7 @@
*/
#include "pitime.h"
#ifndef MICRO_PIP
#ifndef PIP_NO_PROCESS
# include "piincludes_p.h"
# include "piliterals_bytes.h"
@@ -507,4 +507,4 @@ PIString PIProcess::getEnvironmentVariable(const PIString & variable) {
return PIString();
}
#endif // MICRO_PIP
#endif // PIP_NO_PROCESS
+2 -2
View File
@@ -26,7 +26,7 @@
#ifndef PIPROCESS_H
#define PIPROCESS_H
#ifndef MICRO_PIP
#ifndef PIP_NO_PROCESS
# include "pithread.h"
@@ -258,5 +258,5 @@ private:
std::atomic_bool exec_finished;
};
#endif // MICRO_PIP
#endif // PIP_NO_PROCESS
#endif // PIPROCESS_H
+10
View File
@@ -207,11 +207,19 @@ PIVector<PISystemInfo::MountInfo> PISystemInfo::mountInfo(bool ignore_cache) {
PIString confDir() {
return
#ifdef WINDOWS
# ifndef PIP_NO_FILESYSTEM
PIDir::home().path() + "/AppData/Local"
# else
""
# endif
#elif defined(ANDROID)
""
#else
# ifndef PIP_NO_FILESYSTEM
PIDir::home().path() + "/.config"
# else
""
# endif
#endif
;
}
@@ -234,11 +242,13 @@ PIString PISystemInfo::machineKey() {
PISystemInfo * si = instance();
PIByteArray salt;
PIString conf = confDir() + "/.pip_machine_salt";
#ifndef PIP_NO_FILESYSTEM
if (PIFile::isExists(conf)) salt = PIFile::readAll(conf);
if (salt.size_s() != SALT_SIZE) {
salt = generateSalt();
PIFile::writeAll(conf, salt);
}
#endif
ret = si->OS_name + "_" + si->architecture + "_" + si->hostname + "_" + salt.toHex();
}
return ret;
+4 -4
View File
@@ -19,9 +19,9 @@
#include "pisystemtests.h"
#ifndef MICRO_PIP
#ifndef PIP_NO_FILESYSTEM
# include "piconfig.h"
#endif
#endif // !PIP_NO_FILESYSTEM
namespace PISystemTests {
@@ -35,10 +35,10 @@ PISystemTestReader pisystestreader;
PISystemTests::PISystemTestReader::PISystemTestReader() {
#if !defined(WINDOWS) && !defined(MICRO_PIP)
#if !defined(WINDOWS) && !defined(PIP_NO_FILESYSTEM)
PIConfig conf(PIStringAscii("/etc/pip.conf"), PIIODevice::ReadOnly);
time_resolution_ns = conf.getValue(PIStringAscii("time_resolution_ns"), 1).toLong();
time_elapsed_ns = conf.getValue(PIStringAscii("time_elapsed_ns"), 0).toLong();
usleep_offset_us = conf.getValue(PIStringAscii("usleep_offset_us"), 60).toLong();
#endif
#endif // !WINDOWS && !PIP_NO_FILESYSTEM
}
+29 -14
View File
@@ -4,22 +4,22 @@
//! \~english Condition variable for waiting and notification between threads
//! \~russian Переменная условия для ожидания и уведомления между потоками
/*
PIP - Platform Independent Primitives
Condition variable for waiting and notification between threads
Stephan Fomenko
PIP - Platform Independent Primitives
Condition variable for waiting and notification between threads
Stephan Fomenko
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICONDITIONVAR_H
@@ -108,7 +108,7 @@ public:
//! \param condition вызываемый объект или функция, не принимающая аргументов и возвращающая значение, которое может быть оценено как
//! bool. Вызывается повторно, пока не примет значение true
//!
virtual void wait(PIMutex & lk, std::function<bool ()> condition);
virtual void wait(PIMutex & lk, std::function<bool()> condition);
//! \~english Waits for at most \a timeout and returns \c true if awakened before it expires.
@@ -176,4 +176,19 @@ private:
};
#endif // PIP_NO_THREADS
#ifdef PIP_NO_THREADS
class PIConditionVariable {
public:
void wait(PIMutex &) {}
void wait(PIMutex &, std::function<bool()>) {}
bool waitFor(PIMutex &, PISystemTime) { return false; }
bool waitFor(PIMutex &, PISystemTime, std::function<bool()>) { return false; }
bool wait(PIMutex &, PISystemTime) { return true; }
bool wait(PIMutex &, ullong) { return true; }
void notifyOne() {}
void notifyAll() {}
};
#endif // PIP_NO_THREADS
#endif // PICONDITIONVAR_H
+24
View File
@@ -95,4 +95,28 @@ private:
};
#endif // PIP_NO_THREADS
#ifdef PIP_NO_THREADS
//! \~\ingroup Thread
//! \~\brief
//! \~english Dummy mutex for builds without threading support.
//! \~russian Заглушка мьютекса для сборки без поддержки потоков.
class PIMutex {
public:
void lock() {}
void unlock() {}
bool tryLock() { return true; }
void * handle() { return nullptr; }
};
//! \~\ingroup Thread
//! \~\brief
//! \~english Dummy mutex locker for builds without threading support.
//! \~russian Заглушка блокировщика для сборки без поддержки потоков.
class PIMutexLocker {
public:
PIMutexLocker(PIMutex &, bool = true) {}
};
#endif // PIP_NO_THREADS
#endif // PIMUTEX_H
+6 -2
View File
@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
PIReadWriteLock, PIReadLocker, PIWriteLocker
Ivan Pelipenko peri4ko@yandex.ru
PIReadWriteLock, PIReadLocker, PIWriteLocker
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
@@ -151,6 +151,8 @@
#include "pireadwritelock.h"
#ifndef PIP_NO_THREADS
PIReadWriteLock::PIReadWriteLock() {}
@@ -232,3 +234,5 @@ void PIReadWriteLock::unlockRead() {
--reading;
var.notifyAll();
}
#endif // PIP_NO_THREADS
+4
View File
@@ -98,6 +98,8 @@
#include "pisemaphore.h"
#ifndef PIP_NO_THREADS
PISemaphore::PISemaphore(int initial) {
count = initial;
@@ -150,3 +152,5 @@ int PISemaphore::available() const {
PIMutexLocker _ml(mutex);
return count;
}
#endif // PIP_NO_THREADS
+104 -111
View File
@@ -18,39 +18,37 @@
*/
#ifndef PIP_NO_THREADS
#include "pithread.h"
# include "pithread.h"
#include "piincludes_p.h"
#include "piintrospection_threads.h"
#include "piliterals_time.h"
#include "pitime.h"
#include "pitranslator.h"
#ifndef MICRO_PIP
# include "piincludes_p.h"
# include "piintrospection_threads.h"
# include "piliterals_time.h"
# include "pisystemtests.h"
#endif
#ifdef WINDOWS
# include <ioapiset.h>
#endif
#include <signal.h>
#if defined(WINDOWS)
# define __THREAD_FUNC_RET__ uint __stdcall
#elif defined(FREERTOS)
# define __THREAD_FUNC_RET__ void
#else
# define __THREAD_FUNC_RET__ void *
#endif
#ifndef FREERTOS
# define __THREAD_FUNC_END__ 0
#else
# define __THREAD_FUNC_END__
#endif
#if defined(LINUX)
# include <sys/syscall.h>
# define gettid() syscall(SYS_gettid)
#endif
#if defined(MAC_OS) || defined(BLACKBERRY)
# include <pthread.h>
#endif
# include "pitime.h"
# include "pitranslator.h"
# ifdef WINDOWS
# include <ioapiset.h>
# endif
# include <signal.h>
# if defined(WINDOWS)
# define __THREAD_FUNC_RET__ uint __stdcall
# elif defined(FREERTOS)
# define __THREAD_FUNC_RET__ void
# else
# define __THREAD_FUNC_RET__ void *
# endif
# ifndef FREERTOS
# define __THREAD_FUNC_END__ 0
# else
# define __THREAD_FUNC_END__
# endif
# if defined(LINUX)
# include <sys/syscall.h>
# define gettid() syscall(SYS_gettid)
# endif
# if defined(MAC_OS) || defined(BLACKBERRY)
# include <pthread.h>
# endif
__THREAD_FUNC_RET__ thread_function(void * t) {
((PIThread *)t)->__thread_func__();
return __THREAD_FUNC_END__;
@@ -60,13 +58,8 @@ __THREAD_FUNC_RET__ thread_function_once(void * t) {
return __THREAD_FUNC_END__;
}
#ifndef MICRO_PIP
# define REGISTER_THREAD(t) __PIThreadCollection::instance()->registerThread(t)
# define UNREGISTER_THREAD(t) __PIThreadCollection::instance()->unregisterThread(t)
#else
# define REGISTER_THREAD(t)
# define UNREGISTER_THREAD(t)
#endif
//! \addtogroup Thread
//! \{
@@ -457,7 +450,7 @@ __THREAD_FUNC_RET__ thread_function_once(void * t) {
//! \return \c false если таймаут истёк
#ifndef MICRO_PIP
# ifndef PIP_NO_THREADS
__PIThreadCollection * __PIThreadCollection::instance() {
return __PIThreadCollection_Initializer__::__instance__;
@@ -523,18 +516,18 @@ __PIThreadCollection_Initializer__::~__PIThreadCollection_Initializer__() {
}
}
#endif // MICRO_PIP
# endif // PIP_NO_THREADS
PRIVATE_DEFINITION_START(PIThread)
#if defined(WINDOWS)
# if defined(WINDOWS)
void * thread = nullptr;
#elif defined(FREERTOS)
# elif defined(FREERTOS)
TaskHandle_t thread;
#else
# else
pthread_t thread = 0;
sched_param sparam;
#endif
# endif
PRIVATE_DEFINITION_END(PIThread)
@@ -572,25 +565,25 @@ PIThread::~PIThread() {
PIINTROSPECTION_THREAD_DELETE(this);
if (!running_ || PRIVATE->thread == 0) return;
piCout << "[PIThread \"%1\"] Warning, terminate on destructor!"_tr("PIThread").arg(name());
#ifdef FREERTOS
# ifdef FREERTOS
// void * ret(0);
// PICout(PICoutManipulators::DefaultControls) << "~PIThread" << PRIVATE->thread;
// PICout(PICoutManipulators::DefaultControls) << pthread_join(PRIVATE->thread, 0);
PICout(PICoutManipulators::DefaultControls) << "FreeRTOS can't terminate pthreads! waiting for stop";
stopAndWait();
// PICout(PICoutManipulators::DefaultControls) << "stopped!";
#else
# ifndef WINDOWS
# ifdef ANDROID
pthread_kill(PRIVATE->thread, SIGTERM);
# else
pthread_cancel(PRIVATE->thread);
# endif
# else
# ifndef WINDOWS
# ifdef ANDROID
pthread_kill(PRIVATE->thread, SIGTERM);
# else
pthread_cancel(PRIVATE->thread);
# endif
# else
TerminateThread(PRIVATE->thread, 0);
CloseHandle(PRIVATE->thread);
# endif
# endif
#endif
UNREGISTER_THREAD(this);
PIINTROSPECTION_THREAD_STOP(this);
terminating = running_ = false;
@@ -668,32 +661,32 @@ void PIThread::stop() {
void PIThread::terminate() {
piCoutObj << "Warning, terminate!"_tr("PIThread");
// PICout(PICoutManipulators::DefaultControls) << "thread" << this << "terminate ..." << running_;
#ifdef FREERTOS
# ifdef FREERTOS
PICout(PICoutManipulators::DefaultControls) << "FreeRTOS can't terminate pthreads! waiting for stop";
stop(true);
// PICout(PICoutManipulators::DefaultControls) << "stopped!";
#else
# else
if (PRIVATE->thread == 0) return;
UNREGISTER_THREAD(this);
terminating = running_ = false;
tid_ = -1;
// PICout(PICoutManipulators::DefaultControls) << "terminate" << PRIVATE->thread;
# ifndef WINDOWS
# ifdef ANDROID
# ifndef WINDOWS
# ifdef ANDROID
pthread_kill(PRIVATE->thread, SIGTERM);
# else
# else
// pthread_kill(PRIVATE->thread, SIGKILL);
// void * ret(0);
pthread_cancel(PRIVATE->thread);
// pthread_join(PRIVATE->thread, &ret);
# endif
# else
# endif
# else
TerminateThread(PRIVATE->thread, 0);
CloseHandle(PRIVATE->thread);
# endif
# endif
PRIVATE->thread = 0;
end();
#endif // FREERTOS
# endif // FREERTOS
PIINTROSPECTION_THREAD_STOP(this);
// PICout(PICoutManipulators::DefaultControls) << "thread" << this << "terminate ok" << running_;
}
@@ -701,31 +694,31 @@ void PIThread::terminate() {
int PIThread::priority2System(PIThread::Priority p) {
switch (p) {
#if defined(QNX)
# if defined(QNX)
case piLowerst: return 8;
case piLow: return 9;
case piNormal: return 10;
case piHigh: return 11;
case piHighest: return 12;
#elif defined(WINDOWS)
# elif defined(WINDOWS)
case piLowerst: return -2;
case piLow: return -1;
case piNormal: return 0;
case piHigh: return 1;
case piHighest: return 2;
#elif defined(FREERTOS)
# elif defined(FREERTOS)
case piLowerst: return 2;
case piLow: return 3;
case piNormal: return 4;
case piHigh: return 5;
case piHighest: return 6;
#else
# else
case piLowerst: return 2;
case piLow: return 1;
case piNormal: return 0;
case piHigh: return -1;
case piHighest: return -2;
#endif
# endif
default: return 0;
}
return 0;
@@ -736,7 +729,7 @@ bool PIThread::_startThread(void * func) {
terminating = false;
running_ = true;
#ifdef FREERTOS
# ifdef FREERTOS
auto name_ba = createThreadName();
if (xTaskCreate((__THREAD_FUNC_RET__(*)(void *))func,
@@ -749,20 +742,20 @@ bool PIThread::_startThread(void * func) {
return true;
}
#elif defined(WINDOWS)
# elif defined(WINDOWS)
if (PRIVATE->thread) CloseHandle(PRIVATE->thread);
# ifdef CC_GCC
# ifdef CC_GCC
PRIVATE->thread = (void *)_beginthreadex(0, 0, (__THREAD_FUNC_RET__(*)(void *))func, this, CREATE_SUSPENDED, 0);
# else
# else
PRIVATE->thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)func, this, CREATE_SUSPENDED, 0);
# endif
# endif
if (PRIVATE->thread != 0) {
ResumeThread(PRIVATE->thread);
return true;
}
#else
# else
pthread_attr_t attr;
pthread_attr_init(&attr);
@@ -775,7 +768,7 @@ bool PIThread::_startThread(void * func) {
return true;
}
#endif
# endif
running_ = false;
PRIVATE->thread = 0;
@@ -787,30 +780,30 @@ bool PIThread::_startThread(void * func) {
void PIThread::setPriority(PIThread::Priority prior) {
priority_ = prior;
if (!running_ || (PRIVATE->thread == 0)) return;
#ifdef FREERTOS
# ifdef FREERTOS
vTaskPrioritySet(PRIVATE->thread, priority2System(priority_));
#else
# ifndef WINDOWS
# else
# ifndef WINDOWS
// PICout(PICoutManipulators::DefaultControls) << "setPriority" << PRIVATE->thread;
int policy_ = 0;
piZeroMemory(PRIVATE->sparam);
pthread_getschedparam(PRIVATE->thread, &policy_, &(PRIVATE->sparam));
PRIVATE->sparam.
# ifndef LINUX
# ifndef LINUX
sched_priority
# else
# else
__sched_priority
# endif
# endif
= priority2System(priority_);
pthread_setschedparam(PRIVATE->thread, policy_, &(PRIVATE->sparam));
# else
# else
SetThreadPriority(PRIVATE->thread, priority2System(priority_));
# endif
#endif // FREERTOS
# endif
# endif // FREERTOS
}
#ifdef WINDOWS
# ifdef WINDOWS
bool isExists(HANDLE hThread) {
// errorClear();
// piCout << "isExists" << hThread;
@@ -821,7 +814,7 @@ bool isExists(HANDLE hThread) {
// piCout << errorString();
return false;
}
#endif
# endif
bool PIThread::waitForFinish(PISystemTime timeout) {
@@ -857,18 +850,18 @@ bool PIThread::waitForStart(PISystemTime timeout) {
void PIThread::_beginThread() {
#ifndef WINDOWS
# if !defined(ANDROID) && !defined(FREERTOS)
# ifndef WINDOWS
# if !defined(ANDROID) && !defined(FREERTOS)
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, 0);
# endif
# endif
#endif
#ifdef WINDOWS
# ifdef WINDOWS
tid_ = GetCurrentThreadId();
#endif
#ifdef LINUX
# endif
# ifdef LINUX
tid_ = gettid();
#endif
# endif
setPriority(priority_);
setThreadName();
PIINTROSPECTION_THREAD_START(this);
@@ -887,13 +880,13 @@ void PIThread::_runThread() {
if (lockRun) thread_mutex.lock();
// PICout(PICoutManipulators::DefaultControls) << "thread" << this << "lock" << "ok";
// PICout(PICoutManipulators::DefaultControls) << "thread" << this << "run" << "...";
#ifdef PIP_INTROSPECTION
# ifdef PIP_INTROSPECTION
PITimeMeasurer _tm;
#endif
# endif
run();
#ifdef PIP_INTROSPECTION
# ifdef PIP_INTROSPECTION
PIINTROSPECTION_THREAD_RUN_DONE(this, ullong(_tm.elapsed_u()));
#endif
# endif
// PICout(PICoutManipulators::DefaultControls) << "thread" << this << "run" << "ok";
// printf("thread %p tick\n", this);
// PICout(PICoutManipulators::DefaultControls) << "thread" << this << "ret_func" << "...";
@@ -924,20 +917,20 @@ void PIThread::_endThread() {
// PICout(PICoutManipulators::DefaultControls) << "pthread_exit" << (__privateinitializer__.p)->thread;
UNREGISTER_THREAD(this);
PIINTROSPECTION_THREAD_STOP(this);
#if defined(WINDOWS)
# if defined(WINDOWS)
ec.callAndCancel();
# ifdef CC_GCC
# ifdef CC_GCC
_endthreadex(0);
# else
# else
ExitThread(0);
# endif
#elif defined(FREERTOS)
# endif
# elif defined(FREERTOS)
PRIVATE->thread = 0;
#else
# else
PRIVATE->thread = 0;
ec.callAndCancel();
pthread_exit(0);
#endif
# endif
}
@@ -1010,10 +1003,10 @@ void PIThread::runOnce(PIObject * object, const char * handler, const PIString &
delete t;
return;
}
#ifndef MICRO_PIP
# ifndef PIP_NO_THREADS
__PIThreadCollection::instance()->startedAuto(t);
CONNECT0(void, t, stopped, __PIThreadCollection::instance(), stoppedAuto);
#endif
# endif
t->startOnce();
}
@@ -1044,10 +1037,10 @@ void PIThread::runOnce(std::function<void()> func, const PIString & name) {
PIThread * t = new PIThread();
t->setName(name);
t->setSlot(std::move(func));
#ifndef MICRO_PIP
# ifndef PIP_NO_THREADS
__PIThreadCollection::instance()->startedAuto(t);
CONNECT0(void, t, stopped, __PIThreadCollection::instance(), stoppedAuto);
#endif
# endif
t->startOnce();
}
@@ -1063,15 +1056,15 @@ PIByteArray PIThread::createThreadName(int size) const {
void PIThread::setThreadName() {
#ifndef WINDOWS
# ifndef WINDOWS
auto name_ba = createThreadName();
# ifdef MAC_OS
# ifdef MAC_OS
pthread_setname_np((const char *)name_ba.data());
pthread_threadid_np(PRIVATE->thread, (__uint64_t *)&tid_);
# else
# else
pthread_setname_np(PRIVATE->thread, (const char *)name_ba.data());
# endif
# endif
#endif
}
@@ -1079,12 +1072,12 @@ bool PIThread::_waitForFinish(PISystemTime max_tm) {
if (!running_) return true;
state_notifier.waitFor(max_tm);
if (!running_) return true;
#ifdef WINDOWS
# ifdef WINDOWS
if (!isExists(PRIVATE->thread)) {
unlock();
return true;
}
#endif
# endif
return false;
}
#endif // PIP_NO_THREADS
+4 -4
View File
@@ -44,7 +44,7 @@
class PIThread;
#ifndef PIP_NO_THREADS
#ifndef MICRO_PIP
# ifndef PIP_NO_THREADS
class PIIntrospectionThreads;
class PIP_EXPORT __PIThreadCollection: public PIObject {
@@ -75,7 +75,7 @@ public:
};
static __PIThreadCollection_Initializer__ __PIThreadCollection_initializer__;
#endif // MICRO_PIP
# endif // PIP_NO_THREADS
//! \~english Callback executed by %PIThread with the current \a data() pointer.
//! \~russian Обратный вызов, который %PIThread выполняет с текущим указателем \a data().
@@ -99,9 +99,9 @@ typedef std::function<void(void *)> ThreadFunc;
//! проход без повторяющегося цикла обработки очереди.
class PIP_EXPORT PIThread: public PIObject {
PIOBJECT_SUBCLASS(PIThread, PIObject);
#ifndef MICRO_PIP
# ifndef PIP_NO_THREADS
friend class PIIntrospectionThreads;
#endif
# endif
public:
NO_COPY_CLASS(PIThread);
+4
View File
@@ -19,6 +19,8 @@
#include "pithreadnotifier.h"
#ifndef PIP_NO_THREADS
//! \addtogroup Thread
//! \{
//! \class PIThreadNotifier pithreadnotifier.h
@@ -142,3 +144,5 @@ void PIThreadNotifier::notify() {
v.notifyAll();
m.unlock();
}
#endif // PIP_NO_THREADS
+3 -1
View File
@@ -6,7 +6,7 @@
/*
PIP - Platform Independent Primitives
Class for simply notify and wait in different threads
Ivan Pelipenko peri4ko@yandex.ru
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
@@ -27,6 +27,7 @@
#include "piconditionvar.h"
#ifndef PIP_NO_THREADS
//! \~\ingroup Thread
//! \~\brief
@@ -63,5 +64,6 @@ private:
PIMutex m;
PIConditionVariable v;
};
#endif // PIP_NO_THREADS
#endif // PITHREADNOTIFIER_H
+4
View File
@@ -23,6 +23,8 @@
#include "pisysteminfo.h"
#include "pithread.h"
#ifndef PIP_NO_THREADS
//! \addtogroup Thread
//! \{
@@ -166,3 +168,5 @@ void PIThreadPoolLoop::exec(int index_start, int index_count, std::function<void
setFunction(std::move(f));
exec(index_start, index_count);
}
#endif // PIP_NO_THREADS
+6 -2
View File
@@ -1,7 +1,7 @@
/*
PIP - Platform Independent Primitives
Ivan Pelipenko, Stephan Fomenko
Ivan Pelipenko, Stephan Fomenko
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
@@ -21,6 +21,8 @@
#include "pisysteminfo.h"
#ifndef PIP_NO_THREADS
//! \addtogroup Thread
//! \{
//! \class PIThreadPoolWorker pithreadpoolworker.h
@@ -177,7 +179,7 @@ int64_t PIThreadPoolWorker::enqueueTask(std::function<void(int64_t)> func, PIObj
contexts.remove(context);
auto qref = tasks_queue.getRef();
// auto prev_size = qref->size();
// piCout << "deleted" << (void *)context << qref->map<void *>([](const Task & t) { return t.context; });
// piCout << "deleted" << (void *)context << qref->map<void *>([](const Task & t) { return t.context; });
qref->removeWhere([context](const Task & t) { return t.context == context; });
// piCout << prev_size << qref->size() << qref->map<void *>([](const Task & t) { return t.context; });
}));
@@ -236,3 +238,5 @@ void PIThreadPoolWorker::threadFunc(Worker * w) {
taskFinished(task.id);
w->notifier.notify();
}
#endif // PIP_NO_THREADS
+5 -3
View File
@@ -6,7 +6,7 @@
/*
PIP - Platform Independent Primitives
Ivan Pelipenko, Stephan Fomenko
Ivan Pelipenko, Stephan Fomenko
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
@@ -33,6 +33,7 @@
//! \~\brief
//! \~english Fixed-size pool of worker threads for generic-purpose tasks.
//! \~russian Фиксированный пул рабочих потоков для задач общего назначения.
#ifndef PIP_NO_THREADS
class PIP_EXPORT PIThreadPoolWorker: public PIObject {
PIOBJECT(PIThreadPoolWorker)
@@ -109,7 +110,7 @@ public:
template<typename O>
int64_t enqueueTask(O * obj, void (O::*member_func)(int64_t)) {
return enqueueTask([obj, member_func](int64_t id) { (obj->*member_func)(id); },
PIObject::isPIObject(obj) ? dynamic_cast<PIObject *>(obj) : nullptr);
PIObject::isPIObject(obj) ? dynamic_cast<PIObject *>(obj) : nullptr);
}
//! \~english Queue class member method to execution. Returns task ID.
@@ -117,7 +118,7 @@ public:
template<typename O>
int64_t enqueueTask(O * obj, void (O::*member_func)()) {
return enqueueTask([obj, member_func](int64_t) { (obj->*member_func)(); },
PIObject::isPIObject(obj) ? dynamic_cast<PIObject *>(obj) : nullptr);
PIObject::isPIObject(obj) ? dynamic_cast<PIObject *>(obj) : nullptr);
}
//! \~english Remove task with id \a id from queue. Returns if task delete.
@@ -172,6 +173,7 @@ private:
PISet<PIObject *> contexts;
std::atomic_int64_t next_task_id = {0};
};
#endif // PIP_NO_THREADS
#endif // PITHREADPOOLWORKER_H
+1 -1
View File
@@ -31,7 +31,7 @@
# include <mach/clock.h>
// # include <crt_externs.h>
#endif
#ifdef MICRO_PIP
#ifdef PIP_EMBEDDED
# include <sys/time.h>
#endif
+13 -1
View File
@@ -1,6 +1,6 @@
/*
PIP - Platform Independent Primitives
Network address
Network address
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
@@ -20,6 +20,7 @@
#include "pinetworkaddress.h"
// clang-format off
#ifndef PIP_NO_SOCKET
#ifdef QNX
# include <netdb.h>
#else
@@ -33,6 +34,7 @@
# endif
# endif
#endif
#endif // PIP_NO_SOCKET
// clang-format on
@@ -145,11 +147,17 @@ PINetworkAddress PINetworkAddress::resolve(const PIString & host_port) {
PINetworkAddress PINetworkAddress::resolve(const PIString & host, ushort port) {
#ifndef PIP_NO_SOCKET
PINetworkAddress ret(0, port);
hostent * he = gethostbyname(host.dataAscii());
if (!he) return ret;
if (he->h_addr_list[0]) ret.setIP(*((uint *)(he->h_addr_list[0])));
return ret;
#else
(void)host;
(void)port;
return PINetworkAddress();
#endif
}
@@ -162,5 +170,9 @@ void PINetworkAddress::splitIPPort(const PIString & ipp, PIString * _ip, int * _
void PINetworkAddress::initIP(const PIString & _ip) {
#ifndef PIP_NO_SOCKET
ip_ = inet_addr(_ip.dataAscii());
#else
(void)_ip;
#endif
}
+7 -7
View File
@@ -29,7 +29,7 @@
#ifdef QNX
# include <time.h>
#endif
#ifndef MICRO_PIP
#ifndef PIP_EMBEDDED
# include "pisystemtests.h"
#elif defined(ARDUINO)
# include <Arduino.h>
@@ -49,7 +49,7 @@ long long __PIQueryPerformanceCounter() {
// # include <crt_externs.h>
extern clock_serv_t __pi_mac_clock;
#endif
#ifdef MICRO_PIP
#ifdef PIP_EMBEDDED
# include <sys/time.h>
#endif
@@ -246,7 +246,7 @@ PISystemTime PISystemTime::current(bool precise_but_not_system) {
#elif defined(MAC_OS)
mach_timespec_t t_cur;
clock_get_time(__pi_mac_clock, &t_cur);
#elif defined(MICRO_PIP)
#elif defined(PIP_EMBEDDED)
timespec t_cur;
# ifdef ARDUINO
static const uint32_t offSetSinceEpoch_s = 1581897605UL;
@@ -278,7 +278,7 @@ PITimeMeasurer::PITimeMeasurer() {
double PITimeMeasurer::elapsed_n() const {
return (PISystemTime::current(true) - t_st).toNanoseconds()
#ifndef MICRO_PIP
#ifndef PIP_EMBEDDED
- PISystemTests::time_elapsed_ns
#endif
;
@@ -287,7 +287,7 @@ double PITimeMeasurer::elapsed_n() const {
double PITimeMeasurer::elapsed_u() const {
return (PISystemTime::current(true) - t_st).toMicroseconds()
#ifndef MICRO_PIP
#ifndef PIP_EMBEDDED
- PISystemTests::time_elapsed_ns / 1.E+3
#endif
;
@@ -296,7 +296,7 @@ double PITimeMeasurer::elapsed_u() const {
double PITimeMeasurer::elapsed_m() const {
return (PISystemTime::current(true) - t_st).toMilliseconds()
#ifndef MICRO_PIP
#ifndef PIP_EMBEDDED
- PISystemTests::time_elapsed_ns / 1.E+6
#endif
;
@@ -305,7 +305,7 @@ double PITimeMeasurer::elapsed_m() const {
double PITimeMeasurer::elapsed_s() const {
return (PISystemTime::current(true) - t_st).toSeconds()
#ifndef MICRO_PIP
#ifndef PIP_EMBEDDED
- PISystemTests::time_elapsed_ns / 1.E+9
#endif
;
+7 -5
View File
@@ -22,16 +22,16 @@
#ifdef QNX
# include <time.h>
#endif
#ifndef MICRO_PIP
#ifndef PIP_EMBEDDED
# include "pisystemtests.h"
#elif defined(ARDUINO)
# include <Arduino.h>
#elif defined(PICO_SDK)
# include "hardware/time.h"
#endif
#ifdef MICRO_PIP
#else
# include <sys/time.h>
#endif
#ifdef PICO_SDK
extern "C" void sleep_us(unsigned int);
#endif
//! \details
@@ -56,7 +56,9 @@ void piUSleep(int usecs) {
#elif defined(PICO_SDK)
sleep_us(usecs);
#else
# ifndef PIP_NO_THREADS
usecs -= PISystemTests::usleep_offset_us;
# endif
if (usecs > 0) usleep(usecs);
#endif
}
+28 -28
View File
@@ -28,9 +28,9 @@
#include "pistring.h"
#include <typeinfo>
#ifdef MICRO_PIP
#if !defined(__GXX_RTTI__) && !defined(__RTTI__)
# include "pivariant.h"
#endif
#endif // !defined(__GXX_RTTI__) && !defined(__RTTI__)
class __VariantFunctionsBase__ {
@@ -52,21 +52,21 @@ public:
static __VariantFunctions__<T> ret;
return &ret;
}
#ifdef MICRO_PIP
#if !defined(__GXX_RTTI__) && !defined(__RTTI__)
PIString typeName() const final {
static PIString ret(PIVariant::fromValue<T>(T()).typeName());
return ret;
}
#else
PIString typeName() const final {
#if defined(__GXX_RTTI__) || defined(__RTTI__)
# if defined(__GXX_RTTI__) || defined(__RTTI__)
static PIString ret(typeid(T).name());
#else
# else
static PIString ret("unknown");
#endif
# endif
return ret;
}
#endif
#endif // !defined(__GXX_RTTI__) && !defined(__RTTI__)
uint hash() const final {
static uint ret = typeName().hash();
return ret;
@@ -182,27 +182,27 @@ private:
//! \~\brief
//! \~english Registers a readable type name for %PIVariantSimple.
//! \~russian Регистрирует читаемое имя типа для %PIVariantSimple.
#define REGISTER_PIVARIANTSIMPLE(Type) \
template<> \
class __VariantFunctions__<Type>: public __VariantFunctionsBase__ { \
public: \
__VariantFunctionsBase__ * instance() final { \
static __VariantFunctions__<Type> ret; \
return &ret; \
} \
PIString typeName() const final { \
static PIString ret(#Type); \
return ret; \
} \
uint hash() const final { \
static uint ret = typeName().hash(); \
return ret; \
} \
void newT(void *& ptr, const void * value) final { ptr = (void *)(new Type(*(const Type *)value)); } \
void newNullT(void *& ptr) final { ptr = (void *)(new Type()); } \
void assignT(void *& ptr, const void * value) final { *(Type *)ptr = *(const Type *)value; } \
void deleteT(void *& ptr) final { delete (Type *)(ptr); } \
};
#define REGISTER_PIVARIANTSIMPLE(Type) \
template<> \
class __VariantFunctions__<Type>: public __VariantFunctionsBase__ { \
public: \
__VariantFunctionsBase__ * instance() final { \
static __VariantFunctions__<Type> ret; \
return &ret; \
} \
PIString typeName() const final { \
static PIString ret(#Type); \
return ret; \
} \
uint hash() const final { \
static uint ret = typeName().hash(); \
return ret; \
} \
void newT(void *& ptr, const void * value) final { ptr = (void *)(new Type(*(const Type *)value)); } \
void newNullT(void *& ptr) final { ptr = (void *)(new Type()); } \
void assignT(void *& ptr, const void * value) final { *(Type *)ptr = *(const Type *)value; } \
void deleteT(void *& ptr) final { delete (Type *)(ptr); } \
};
REGISTER_PIVARIANTSIMPLE(std::function<void(void *)>)
+7 -7
View File
@@ -21,9 +21,9 @@
#include "colors_p.h"
#include "pipropertystorage.h"
#ifndef MICRO_PIP
#ifndef PIP_NO_FILESYSTEM
# include "piiodevice.h"
#endif
#endif // PIP_NO_FILESYSTEM
int PIVariantTypes::Enum::selectedValue() const {
@@ -84,11 +84,11 @@ PIStringList PIVariantTypes::Enum::names() const {
PIVariantTypes::IODevice::IODevice() {
#ifndef MICRO_PIP
#ifndef PIP_NO_FILESYSTEM
mode = PIIODevice::ReadWrite;
#else
mode = 0; // TODO: PIIODevice for MICRO PIP
#endif // MICRO_PIP
mode = 0; // TODO: PIIODevice for PIP_NO_FILESYSTEM
#endif // PIP_NO_FILESYSTEM
options = 0;
}
@@ -121,12 +121,12 @@ PIString PIVariantTypes::IODevice::toPICout() const {
}
if (rwc == 1) s += "o";
s += ", flags=";
#ifndef MICRO_PIP // TODO: PIIODevice for MICRO PIP
#ifndef PIP_NO_FILESYSTEM // TODO: PIIODevice for PIP_NO_FILESYSTEM
if (options != 0) {
if (((PIIODevice::DeviceOptions)options)[PIIODevice::BlockingRead]) s += " br";
if (((PIIODevice::DeviceOptions)options)[PIIODevice::BlockingWrite]) s += " bw";
}
#endif // MICRO_PIP
#endif // PIP_NO_FILESYSTEM
PIPropertyStorage ps = get();
for (const auto & p: ps) {
s += ", " + p.name + "=\"" + p.value.toString() + "\"";