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
+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);