PIIODevice registration dramatically optimization

This commit is contained in:
2022-04-30 11:21:57 +03:00
parent 19e4eee222
commit 2bbdbc3ac9
29 changed files with 138 additions and 78 deletions

View File

@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0)
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
project(pip)
set(pip_MAJOR 2)
set(pip_MINOR 37)
set(pip_MINOR 38)
set(pip_REVISION 0)
set(pip_SUFFIX )
set(pip_COMPANY SHS)

View File

@@ -3,7 +3,7 @@ void _() {
//! [0]
class SomeIO: public PIIODevice {
PIIODEVICE(SomeIO)
PIIODEVICE(SomeIO, "myio")
public:
SomeIO(): PIIODevice() {}
protected:
@@ -19,9 +19,8 @@ protected:
// write to your device here
return written_bytes;
}
PIString fullPathPrefix() const {return "myio";}
void configureFromFullPath(const PIString & full_path) {
// parse full_path and configure device there
// parse full_path and configure device here
}
};
REGISTER_DEVICE(SomeIO)

View File

@@ -34,7 +34,7 @@
class PIP_CLOUD_EXPORT PICloudClient: public PIIODevice, public PICloudBase
{
PIIODEVICE(PICloudClient)
PIIODEVICE(PICloudClient, "")
public:
explicit PICloudClient(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
virtual ~PICloudClient();

View File

@@ -32,14 +32,14 @@
class PIP_CLOUD_EXPORT PICloudServer: public PIIODevice, public PICloudBase
{
PIIODEVICE(PICloudServer)
PIIODEVICE(PICloudServer, "")
public:
//! PICloudServer
explicit PICloudServer(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
virtual ~PICloudServer();
class Client : public PIIODevice {
PIIODEVICE(PICloudServer::Client)
PIIODEVICE(PICloudServer::Client, "")
friend class PICloudServer;
public:
Client(PICloudServer * srv = nullptr, uint id = 0);

View File

@@ -48,6 +48,18 @@
//! \}
bool PIConstChars::startsWith(const PIConstChars & str) const {
if (size() < str.size()) return false;
return str == left(str.size());
}
bool PIConstChars::endsWith(const PIConstChars & str) const {
if (size() < str.size()) return false;
return str == right(str.size());
}
PIConstChars PIConstChars::mid(const int start, const int len) const {
int s = start, l = len;
if (l == 0 || s >= (int)size() || isEmpty()) return PIConstChars("");

View File

@@ -94,6 +94,14 @@ public:
//! \~russian Возвращает длину строки в символах.
inline ssize_t size_s() const {return len;}
//! \~english Returns if string starts with "str".
//! \~russian Возвращает начинается ли строка со "str".
bool startsWith(const PIConstChars & str) const;
//! \~english Returns if string ends with "str".
//! \~russian Возвращает оканчивается ли строка на "str".
bool endsWith(const PIConstChars & str) const;
//! \~english Returns part of string from character at index "start" and maximum length "len".
//! \~russian Возвращает подстроку от символа "start" и максимальной длиной "len".
//! \~\sa \a left(), \a right()

View File

@@ -250,7 +250,7 @@ PIStringList PIObject::scopeList() const {
PIMutexLocker ml(__meta_mutex());
const PIVector<const char *> & scope(__meta_data()[classNameID()].scope_list);
for (const char * c: scope)
ret = PIStringAscii(c);
ret << PIStringAscii(c);
return ret;
}
@@ -727,7 +727,7 @@ void PIObject::dump(const PIString & line_prefix) const {
#ifndef MICRO_PIP
void dumpApplication() {
void dumpApplication(bool with_objects) {
PIMutexLocker _ml(PIObject::mutexObjects());
//printf("dump application ...\n");
PIDateTime cd = PIDateTime::current();
@@ -745,22 +745,24 @@ void dumpApplication() {
PICout(PICoutManipulators::AddNewLine) << " uptime: " << PITime::fromSystemTime(cd.toSystemTime() - pi->execDateTime.toSystemTime()).toString();
PICout(PICoutManipulators::AddNewLine) << " PIObjects {";
PICout(PICoutManipulators::AddNewLine) << " count: " << PIObject::objects().size_s();
piForeachC (PIObject * o, PIObject::objects())
o->dump(" ");
if (with_objects) {
for (const PIObject * o: PIObject::objects())
o->dump(" ");
}
PICout(PICoutManipulators::AddNewLine) << " }";
PICout(PICoutManipulators::AddNewLine) << "}";
//printf("dump application done\n");
}
bool dumpApplicationToFile(const PIString & path) {
bool dumpApplicationToFile(const PIString & path, bool with_objects) {
PIFile f(path + "_tmp");
f.setName("__S__DumpFile");
f.clear();
if (!f.open(PIIODevice::WriteOnly)) return false;
bool ba = PICout::isBufferActive();
PICout::setBufferActive(true, true);
dumpApplication();
dumpApplication(with_objects);
f << PICout::buffer();
f.close();
PICout::setBufferActive(ba, true);

View File

@@ -39,7 +39,7 @@ typedef void (*Handler)(void * );
class PIP_EXPORT PIObject {
#ifndef MICRO_PIP
friend class PIObjectManager;
friend void dumpApplication();
friend void dumpApplication(bool);
friend class PIIntrospection;
#endif
typedef PIObject __PIObject__;
@@ -587,8 +587,8 @@ private:
};
#ifndef MICRO_PIP
PIP_EXPORT void dumpApplication();
PIP_EXPORT bool dumpApplicationToFile(const PIString & path);
PIP_EXPORT void dumpApplication(bool with_objects = true);
PIP_EXPORT bool dumpApplicationToFile(const PIString & path, bool with_objects = true);
#endif
#endif // PIOBJECT_H

View File

@@ -791,7 +791,7 @@ void PIBinaryLog::configureFromVariantDevice(const PIPropertyStorage & d) {
}
void PIBinaryLog::propertyChanged(const PIString &s) {
void PIBinaryLog::propertyChanged(const char * s) {
default_id = property("defaultID").toInt();
rapid_start = property("rapidStart").toBool();
play_mode = (PlayMode)property("playMode").toInt();

View File

@@ -31,7 +31,7 @@
class PIP_EXPORT PIBinaryLog: public PIIODevice
{
PIIODEVICE(PIBinaryLog)
PIIODEVICE(PIBinaryLog, "binlog")
public:
explicit PIBinaryLog();
virtual ~PIBinaryLog();
@@ -288,7 +288,6 @@ public:
static bool cutBinLog(const BinLogInfo & src, const PIString & dst, int from, int to);
protected:
PIString fullPathPrefix() const {return PIStringAscii("binlog");}
PIString constructFullPathDevice() const;
void configureFromFullPathDevice(const PIString & full_path);
PIPropertyStorage constructVariantDevice() const;
@@ -297,7 +296,7 @@ protected:
int writeDevice(const void * data, int size) {return writeBinLog(default_id, data, size);}
bool openDevice();
bool closeDevice();
void propertyChanged(const PIString &);
void propertyChanged(const char * s);
bool threadedRead(uchar *readed, int size);
void threadedReadTerminated() {pausemutex.unlock();}
DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Reliable;}

View File

@@ -31,7 +31,7 @@
class PIP_EXPORT PICAN: public PIIODevice
{
PIIODEVICE(PICAN)
PIIODEVICE(PICAN, "can")
public:
explicit PICAN(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
virtual ~PICAN();
@@ -45,7 +45,6 @@ protected:
bool closeDevice();
int readDevice(void * read_to, int max_size);
int writeDevice(const void * data, int max_size);
PIString fullPathPrefix() const {return PIStringAscii("can");}
PIString constructFullPathDevice() const;
void configureFromFullPathDevice(const PIString & full_path);
PIPropertyStorage constructVariantDevice() const;

View File

@@ -21,6 +21,7 @@
#include "piconfig.h"
#include "pisysteminfo.h"
#include "pipropertystorage.h"
#include "piconstchars.h"
#ifdef QNX
# include <net/if.h>
# include <net/if_dl.h>
@@ -919,10 +920,11 @@ bool PIEthernet::configureDevice(const void * e_main, const void * e_parent) {
}
void PIEthernet::propertyChanged(const PIString & name) {
if (name.endsWith("Timeout")) applyTimeouts();
if (name == "TTL") applyOptInt(IPPROTO_IP, IP_TTL, TTL());
if (name == "MulticastTTL") applyOptInt(IPPROTO_IP, IP_MULTICAST_TTL, multicastTTL());
void PIEthernet::propertyChanged(const char * name) {
PIConstChars pn(name);
if (pn.endsWith("Timeout")) applyTimeouts();
if (pn == "TTL") applyOptInt(IPPROTO_IP, IP_TTL, TTL());
if (pn == "MulticastTTL") applyOptInt(IPPROTO_IP, IP_MULTICAST_TTL, multicastTTL());
}

View File

@@ -38,7 +38,7 @@ class
class PIP_EXPORT PIEthernet: public PIIODevice
{
PIIODEVICE(PIEthernet)
PIIODEVICE(PIEthernet, "eth")
friend class PIPeer;
public:
@@ -462,9 +462,8 @@ public:
protected:
explicit PIEthernet(int sock, PIString ip_port);
void propertyChanged(const PIString & name);
void propertyChanged(const char * name);
PIString fullPathPrefix() const {return PIStringAscii("eth");}
PIString constructFullPathDevice() const;
void configureFromFullPathDevice(const PIString & full_path);
PIPropertyStorage constructVariantDevice() const;

View File

@@ -32,7 +32,7 @@
class PIP_EXPORT PIFile: public PIIODevice
{
PIIODEVICE(PIFile)
PIIODEVICE(PIFile, "file")
public:
//! Constructs an empty file
@@ -289,7 +289,6 @@ public:
//! \}
protected:
PIString fullPathPrefix() const {return PIStringAscii("file");}
PIString constructFullPathDevice() const;
void configureFromFullPathDevice(const PIString & full_path);
PIPropertyStorage constructVariantDevice() const;

View File

@@ -31,7 +31,7 @@
class PIP_EXPORT PIIOByteArray: public PIIODevice
{
PIIODEVICE(PIIOByteArray)
PIIODEVICE(PIIOByteArray, "")
public:
//! Contructs %PIIOByteArray with \"buffer\" content and \"mode\" open mode

View File

@@ -84,7 +84,6 @@
//!
//! \section PIIODevice_sec7 Creating devices by unambiguous string
//! There are some virtual functions to describe child class without its declaration.
//! \n \a fullPathPrefix() should returns unique prefix of device
//! \n \a constructFullPath() should returns full unambiguous string, contains prefix and all device parameters
//! \n \a configureFromFullPath() provide configuring device from full unambiguous string without prefix and "://"
//! \n Macro PIIODEVICE should be used instead of PIOBJECT
@@ -265,15 +264,14 @@ void PIIODevice::write_func() {
}
PIIODevice * PIIODevice::newDeviceByPrefix(const PIString & prefix) {
if (prefix.isEmpty()) return 0;
PIVector<const PIObject * > rd(PICollection::groupElements("__PIIODevices__"));
piForeachC (PIObject * d, rd) {
if (prefix == ((const PIIODevice * )d)->fullPathPrefix()) {
return ((const PIIODevice * )d)->copy();
}
PIIODevice * PIIODevice::newDeviceByPrefix(const char * prefix) {
if (!prefix) return nullptr;
PIConstChars p(prefix);
for (const auto & i: fabrics()) {
if (i.first == p)
return i.second();
}
return 0;
return nullptr;
}
@@ -427,7 +425,7 @@ bool PIIODevice::configure(const PIString & config_file, const PIString & sectio
PIString PIIODevice::constructFullPath() const {
return fullPathPrefix() + "://" + constructFullPathDevice() + fullPathOptions();
return PIStringAscii(fullPathPrefix()) + PIStringAscii("://") + constructFullPathDevice() + fullPathOptions();
}
@@ -489,14 +487,21 @@ void PIIODevice::splitFullPath(PIString fpwm, PIString * full_path, DeviceMode *
PIStringList PIIODevice::availablePrefixes() {
PIStringList ret;
PIVector<const PIObject * > rd(PICollection::groupElements("__PIIODevices__"));
piForeachC (PIObject * d, rd) {
ret << ((const PIIODevice * )d)->fullPathPrefix();
}
for (const auto & i: fabrics())
ret << i.first.toString();
return ret;
}
void PIIODevice::registerDevice(const char * prefix, PIIODevice * (*fabric)()) {
PIConstChars p(prefix);
if (p.isEmpty()) return;
//printf("registerDevice %s %d %d\n", prefix, p.isEmpty(), fabrics().size());
if (!fabrics().contains(p))
fabrics()[p] = fabric;
}
PIString PIIODevice::fullPathOptions() const {
if (mode_ == ReadWrite && options_ == 0) return PIString();
PIString ret(" (");
@@ -511,8 +516,8 @@ PIString PIIODevice::fullPathOptions() const {
PIIODevice * PIIODevice::createFromFullPath(const PIString & full_path) {
PIString prefix = full_path.left(full_path.find(":"));
PIIODevice * nd = newDeviceByPrefix(prefix);
if (!nd) return 0;
PIIODevice * nd = newDeviceByPrefix(prefix.dataAscii());
if (!nd) return nullptr;
nd->configureFromFullPath(full_path.mid(prefix.length() + 3));
cacheFullPath(full_path, nd);
return nd;
@@ -520,8 +525,8 @@ PIIODevice * PIIODevice::createFromFullPath(const PIString & full_path) {
PIIODevice * PIIODevice::createFromVariant(const PIVariantTypes::IODevice & d) {
PIIODevice * nd = newDeviceByPrefix(d.prefix);
if (!nd) return 0;
PIIODevice * nd = newDeviceByPrefix(d.prefix.dataAscii());
if (!nd) return nullptr;
nd->configureFromVariant(d);
return nd;
}
@@ -550,6 +555,12 @@ void PIIODevice::cacheFullPath(const PIString & full_path, const PIIODevice * d)
}
PIMap<PIConstChars, PIIODevice * (*)()> & PIIODevice::fabrics() {
static PIMap<PIConstChars, PIIODevice * (*)()> ret;
return ret;
}
bool PIIODevice::threadedRead(uchar *readed, int size) {
// piCout << "iodevice threaded read";
if (ret_func_ != 0) return ret_func_(ret_data_, readed, size);

View File

@@ -27,7 +27,6 @@
#define PIIODEVICE_H
#include "piinit.h"
#include "picollection.h"
#include "pitimer.h"
#include "piqueue.h"
@@ -42,16 +41,26 @@ typedef bool (*ReadRetFunc)(void * , uchar * , int );
# define REGISTER_DEVICE(class)
//! \relatesalso PIIODevice \brief Use this macro instead of PIOBJECT when describe your own PIIODevice
# define PIIODEVICE(class)
# define PIIODEVICE(class, "prefix")
#else
# define REGISTER_DEVICE(name) ADD_NEW_TO_COLLECTION_WITH_NAME(__PIIODevices__, name, __S__collection_##name##__)
# define PIIODEVICE(name) PIOBJECT_SUBCLASS(name, PIIODevice) PIIODevice * copy() const {return new name();}
# define REGISTER_DEVICE(name) \
STATIC_INITIALIZER_BEGIN \
PIIODevice::registerDevice(name::fullPathPrefixS(), []()->PIIODevice*{return new name();});\
STATIC_INITIALIZER_END
# define PIIODEVICE(name, prefix) \
PIOBJECT_SUBCLASS(name, PIIODevice) \
PIIODevice * copy() const {return new name();} \
public: \
virtual const char * fullPathPrefix() const {return prefix;} \
static const char * fullPathPrefixS() {return prefix;} \
private:
#endif
class PIP_EXPORT PIIODevice: public PIThread
{
PIOBJECT_SUBCLASS(PIIODevice, PIThread)
@@ -228,8 +237,10 @@ public:
bool configure(const PIString & config_file, const PIString & section, bool parent_section = false);
//! Reimplement to construct full unambiguous string prefix. \ref PIIODevice_sec7
virtual PIString fullPathPrefix() const {return PIString();}
//! Returns full unambiguous string prefix. \ref PIIODevice_sec7
virtual const char * fullPathPrefix() const {return "";}
static const char * fullPathPrefixS() {return "";}
//! Returns full unambiguous string, describes this device, \a fullPathPrefix() + "://"
PIString constructFullPath() const;
@@ -260,6 +271,8 @@ public:
//! Returns fullPath prefixes of all registered devices
static PIStringList availablePrefixes();
static void registerDevice(const char * prefix, PIIODevice*(*fabric)());
EVENT_HANDLER(bool, open);
EVENT_HANDLER1(bool, open, const PIString &, _path);
@@ -386,7 +399,7 @@ protected:
//! Invoked after hard write thread stop
virtual void threadedWriteTerminated() {;}
static PIIODevice * newDeviceByPrefix(const PIString & prefix);
static PIIODevice * newDeviceByPrefix(const char * prefix);
void terminate();
@@ -408,6 +421,7 @@ private:
void run();
void end() {terminate();}
static void cacheFullPath(const PIString & full_path, const PIIODevice * d);
static PIMap<PIConstChars, PIIODevice*(*)()> & fabrics();
PITimer timer;
PITimeMeasurer tm;

View File

@@ -31,7 +31,7 @@
class PIP_EXPORT PIIOString: public PIIODevice
{
PIIODEVICE(PIIOString)
PIIODEVICE(PIIOString, "")
public:
//! Contructs %PIIOString with \"string\" content and \"mode\" open mode

View File

@@ -31,7 +31,7 @@
class PIP_EXPORT PIPeer: public PIIODevice
{
PIIODEVICE(PIPeer)
PIIODEVICE(PIPeer, "peer")
private:
class PeerData;
@@ -168,7 +168,6 @@ private:
bool openDevice();
bool closeDevice();
PIString fullPathPrefix() const {return PIStringAscii("peer");}
PIString constructFullPathDevice() const;
void configureFromFullPathDevice(const PIString &full_path);
PIPropertyStorage constructVariantDevice() const;

View File

@@ -31,7 +31,7 @@
class PIP_EXPORT PISerial: public PIIODevice
{
PIIODEVICE(PISerial)
PIIODEVICE(PISerial, "ser")
public:
//! Contructs an empty %PISerial
@@ -231,7 +231,6 @@ public:
//! \}
protected:
PIString fullPathPrefix() const {return PIStringAscii("ser");}
PIString constructFullPathDevice() const;
void configureFromFullPathDevice(const PIString & full_path);
PIPropertyStorage constructVariantDevice() const;

View File

@@ -31,7 +31,7 @@
class PIP_EXPORT PISharedMemory: public PIIODevice
{
PIIODEVICE(PISharedMemory)
PIIODEVICE(PISharedMemory, "shm")
public:
explicit PISharedMemory();
@@ -76,7 +76,6 @@ public:
protected:
bool openDevice();
bool closeDevice();
PIString fullPathPrefix() const {return PIStringAscii("shm");}
PIString constructFullPathDevice() const;
void configureFromFullPathDevice(const PIString & full_path);
PIPropertyStorage constructVariantDevice() const;

View File

@@ -31,7 +31,7 @@
class PIP_EXPORT PISPI: public PIIODevice
{
PIIODEVICE(PISPI)
PIIODEVICE(PISPI, "spi")
public:
explicit PISPI(const PIString & path = PIString(), uint speed_hz = 1000000, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
virtual ~PISPI();
@@ -67,7 +67,6 @@ protected:
int readDevice(void * read_to, int max_size);
int writeDevice(const void * data, int max_size);
PIString fullPathPrefix() const {return PIStringAscii("spi");}
PIString constructFullPathDevice() const;
void configureFromFullPathDevice(const PIString & full_path);
PIPropertyStorage constructVariantDevice() const;

View File

@@ -31,7 +31,7 @@
class PIP_EXPORT PITransparentDevice: public PIIODevice
{
PIIODEVICE(PITransparentDevice)
PIIODEVICE(PITransparentDevice, "tr")
public:
//! Contructs empty %PITransparentDevice
@@ -44,7 +44,6 @@ protected:
bool closeDevice();
int readDevice(void * read_to, int max_size);
int writeDevice(const void * data, int max_size);
PIString fullPathPrefix() const {return PIStringAscii("tr");}
DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Reliable;}
PIMutex que_mutex;

View File

@@ -63,7 +63,7 @@ struct usb_dev_handle;
class PIP_EXPORT PIUSB: public PIIODevice
{
PIIODEVICE(PIUSB)
PIIODEVICE(PIUSB, "usb")
public:
explicit PIUSB(ushort vid = 0, ushort pid = 0);
virtual ~PIUSB();
@@ -160,7 +160,6 @@ public:
void flush();
protected:
PIString fullPathPrefix() const {return PIStringAscii("usb");}
bool configureDevice(const void * e_main, const void * e_parent = 0);
PIString constructFullPathDevice() const;
void configureFromFullPathDevice(const PIString & full_path);

View File

@@ -225,7 +225,7 @@ PIDiagnostics::Entry PIDiagnostics::calcHistory(PIQueue<Entry> & hist, int & cnt
}
void PIDiagnostics::propertyChanged(const PIString &) {
void PIDiagnostics::propertyChanged(const char *) {
float disct = property("disconnectTimeout").toFloat();
changeDisconnectTimeout(disct);
}

View File

@@ -140,7 +140,7 @@ private:
void tick(void *, int);
Entry calcHistory(PIQueue<Entry> & hist, int & cnt);
void propertyChanged(const PIString &);
void propertyChanged(const char *);
void changeDisconnectTimeout(float disct);
PIQueue<Entry> history_rec, history_send;

View File

@@ -107,7 +107,7 @@ void PIPacketExtractor::construct() {
}
void PIPacketExtractor::propertyChanged(const PIString &) {
void PIPacketExtractor::propertyChanged(const char *) {
packetSize_ = property("packetSize").toInt();
mode_ = (SplitMode)(property("splitMode").toInt());
dataSize = property("payloadSize").toInt();

View File

@@ -33,7 +33,7 @@ typedef bool (*PacketExtractorCheckFunc)(void * , uchar * , uchar * , int );
class PIP_EXPORT PIPacketExtractor: public PIIODevice
{
PIIODEVICE(PIPacketExtractor)
PIIODEVICE(PIPacketExtractor, "pckext")
friend class PIConnection;
public:
@@ -161,11 +161,10 @@ protected:
private:
void construct();
void propertyChanged(const PIString & );
void propertyChanged(const char *);
int readDevice(void * read_to, int max_size) {if (dev == 0) return -1; return dev->read(read_to, max_size);}
int writeDevice(const void * data, int max_size) {if (dev == 0) return -1; return dev->write(data, max_size);}
bool threadedRead(uchar * readed, int size);
PIString fullPathPrefix() const {return PIStringAscii("pckext");}
PIString constructFullPathDevice() const;
bool openDevice() {if (dev == 0) return false; return dev->open();}
bool closeDevice() {if (dev == 0) return false; return dev->close();}

View File

@@ -38,15 +38,38 @@ int main(int argc, char * argv[]) {
cmp(PIConstChars("1a"), PIConstChars("1b"));
cmp(PIConstChars("1c"), PIConstChars("1b"));*/
PIMap<PIConstChars, int> map;
/*PIMap<PIConstChars, int> map;
map[PIConstChars()] = 0;
map[PIConstChars()] = -1;
map["_2"] = 22;
map["1"] = 11;
map["__3"] = 33;
map["10"] = 10;
map[""] = 999;
piCout << map;
piCout << PIConstChars().toString();
piCout << PIConstChars("").toString();
piCout << PIConstChars("str").toString();
PIConstChars s = " 1 2 \t";
piCout << "trim:";
PICout(DefaultControls | AddQuotes) << s.trimmed();
PICout(DefaultControls | AddQuotes) << s;
PICout(DefaultControls | AddQuotes) << s.isEmpty();*/
/*piCout << PIIODevice::availablePrefixes();
auto * d = PIIODevice::createFromFullPath("ser://COM1");
piCout << "";
piCout << d;
d->dump();
d = PIIODevice::createFromFullPath("eth://udp:127.0.0.1:5000");
piCout << "";
piCout << d;
d->dump();*/
piCout << "";
dumpApplication();
return 0;
auto rstr = PIString::fromUTF8("ascii русский!");