diff --git a/main.cpp b/main.cpp
index 7a09a0a5..29e5637c 100644
--- a/main.cpp
+++ b/main.cpp
@@ -6,7 +6,7 @@
#include "piethernet.h"
#include "piintrospection.h"
#include "pifile.h"
-#include "piprocess.h"
+#include "pisingleapplication.h"
//struct MS {
// //MS() {i = 0; f = 0.;}
@@ -33,9 +33,13 @@ public:
int main (int argc, char * argv[]) {
- //PIProcess proc;
- PIProcess::execIndependent("D:/orders/libs_build_win/pip/utils/system_daemon/pisd.exe", PIStringList() << "-d" << "-n" << "peer");
- piMSleep(1000);
+ PISingleApplication sa("app");
+ if (!sa.isFirst())
+ sa.sendMessage(PIString("message to first").toByteArray());
+ else
+ piMSleep(5000);
+ //piCout << PIString(argv[1]).toInt();
+ //sh.destroy();
//proc.terminate();
/*PIByteArray v = PIString("Mandfg;kjngel").toByteArray();
PIByteArray b64 = convertToBase64(v);
diff --git a/src/io/pifile.h b/src/io/pifile.h
index 55648c9e..a3125ca6 100755
--- a/src/io/pifile.h
+++ b/src/io/pifile.h
@@ -83,7 +83,7 @@ public:
bool isHidden() const {return flags[Hidden];}
};
- //! Constructs a file with path "path" nad open mode "type"
+ //! Constructs a file with path "path" and open mode "mode"
explicit PIFile(const PIString & path, DeviceMode mode = ReadWrite);
PIFile(const PIFile & other);
diff --git a/src/io/piiomodule.h b/src/io/piiomodule.h
index 6c0cb47c..106deb98 100644
--- a/src/io/piiomodule.h
+++ b/src/io/piiomodule.h
@@ -34,5 +34,6 @@
#include "pipacketextractor.h"
#include "piprotocol.h"
#include "piconnection.h"
+#include "pisharedmemory.h"
#endif // PIIOMODULE_H
diff --git a/src/io/pisharedmemory.cpp b/src/io/pisharedmemory.cpp
new file mode 100644
index 00000000..35aba568
--- /dev/null
+++ b/src/io/pisharedmemory.cpp
@@ -0,0 +1,240 @@
+/*
+ PIP - Platform Independent Primitives
+ File
+ Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "pisharedmemory.h"
+#ifdef WINDOWS
+
+#endif
+#if defined(QNX) || defined(ANDROID)
+
+#endif
+#ifdef MAC_OS
+
+#endif
+#ifdef LINUX
+# include
+# include
+# include
+#endif
+
+
+/*! \class PISharedMemory
+ * \brief Shared memory
+ *
+ * \section PISharedMemory_sec0 Synopsis
+ * This class provide access to local file. You can manipulate
+ * binary content or use this class as text stream. To binary
+ * access there are function \a read(), \a write(), and many
+ * \a writeBinary() functions. For write variables to file in
+ * their text representation threr are many "<<" operators.
+ *
+ * \section PISharedMemory_sec1 Position
+ * Each opened file has a read/write position - logical position
+ * in the file content you read from or you write to. You can
+ * find out current position with function \a pos(). Function
+ * \a seek(llong position) move position to position "position",
+ * \a seekToBegin() move position to the begin of file,
+ * \a seekToEnd() move position to the end of file.
+ *
+ */
+
+//REGISTER_DEVICE(PISharedMemory);
+
+PRIVATE_DEFINITION_START(PISharedMemory)
+ PIByteArray name;
+#ifdef WINDOWS
+ HANDLE map;
+ void * data;
+#endif
+#ifdef LINUX
+ void * data;
+ bool owner;
+#endif
+PRIVATE_DEFINITION_END(PISharedMemory)
+
+
+PISharedMemory::PISharedMemory(): PIIODevice() {
+ initPrivate();
+ dsize = -1;
+}
+
+
+PISharedMemory::PISharedMemory(const PIString & shm_name, int size, PIIODevice::DeviceMode mode): PIIODevice(shm_name, mode) {
+ initPrivate();
+ dsize = size;
+ if (!shm_name.isEmpty())
+ open();
+}
+
+
+PISharedMemory::PISharedMemory(const PISharedMemory & other) {
+ initPrivate();
+ dsize = other.dsize;
+ setPath(other.path());
+ mode_ = other.mode_;
+}
+
+
+bool PISharedMemory::openDevice() {
+ close();
+#ifdef WINDOWS
+ DWORD m = PAGE_READWRITE;
+ if (!isWriteable()) m = PAGE_READONLY;
+ PRIVATE->name = ("Global\\PIP_SHM_" + path()).toByteArray();
+ PRIVATE->name.push_back(0);
+ PRIVATE->map = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, m, 0, (DWORD)dsize, (const char *)PRIVATE->name.data());
+ if (!PRIVATE->map) {
+ piCoutObj << "CreateFileMapping error," << errorString();
+ return false;
+ }
+ if (!isWriteable()) m = FILE_MAP_READ;
+ else m = FILE_MAP_ALL_ACCESS;
+ PRIVATE->data = MapViewOfFile(PRIVATE->map, m, 0, 0, dsize);
+ if (!PRIVATE->data) {
+ piCoutObj << "MapViewOfFile error," << errorString();
+ CloseHandle(PRIVATE->map);
+ return false;
+ }
+ //piCout << PRIVATE->map << PRIVATE->data;
+#endif
+#ifdef LINUX
+ int m = O_RDWR;
+ if (!isWriteable()) m = O_RDONLY;
+ PRIVATE->name = ("/pip_shm_" + path()).toByteArray();
+ PRIVATE->name.push_back(0);
+ int fd = shm_open((const char *)PRIVATE->name.data(), m, 0777);
+ //piCout << "try open" << PICoutManipulators::Hex << fd;
+ if (fd < 0) {
+ //piCoutObj << "shm_open error," << errorString();
+ fd = shm_open((const char *)PRIVATE->name.data(), m | O_CREAT, 0777);
+ //piCout << "try create" << PICoutManipulators::Hex << (m | O_CREAT) << fd;
+ if (fd < 0) {
+ piCoutObj << "shm_open error," << errorString();
+ return false;
+ }
+ PRIVATE->owner = true;
+ ftruncate(fd, dsize);
+ //piCout << "created" << fd;
+ }
+ m = PROT_WRITE;
+ if (!isWriteable()) m = PROT_READ;
+ PRIVATE->data = mmap(0, dsize, m, MAP_SHARED, fd, 0);
+ ::close(fd);
+ if (!PRIVATE->data) {
+ piCoutObj << "mmap error," << errorString();
+ return false;
+ }
+ //piCout << "opened" << PRIVATE->data;
+#endif
+ return true;
+}
+
+
+bool PISharedMemory::closeDevice() {
+#ifdef WINDOWS
+ if (PRIVATE->data) UnmapViewOfFile(PRIVATE->data);
+ if (PRIVATE->map) CloseHandle(PRIVATE->map);
+#endif
+#ifdef LINUX
+ //piCout << "close" << PIString(PRIVATE->name) << PRIVATE->data;
+ if (PRIVATE->data) munmap(PRIVATE->data, dsize);
+ if (PRIVATE->owner) {
+ //if (!PRIVATE->name.isEmpty()) {
+ //piCout << "unlink" << PIString(PRIVATE->name);
+ shm_unlink((const char *)PRIVATE->name.data());
+ }
+ //if (fd > 0)
+#endif
+ initPrivate();
+ return true;
+}
+
+
+void PISharedMemory::initPrivate() {
+#ifdef WINDOWS
+ PRIVATE->map = 0;
+ PRIVATE->data = 0;
+#endif
+#ifdef LINUX
+ PRIVATE->data = 0;
+ PRIVATE->owner = false;
+#endif
+}
+
+
+PIByteArray PISharedMemory::readAll() {
+ if (dsize <= 0) return PIByteArray();
+#ifdef WINDOWS
+ if (!PRIVATE->data) return PIByteArray();
+#endif
+#ifdef LINUX
+ if (!PRIVATE->data) return PIByteArray();
+#endif
+ PIByteArray a(dsize);
+ read(a.data(), a.size_s());
+ /*llong cp = pos();
+ if (forceRead) {
+ seekToBegin();
+ while (!isEnd())
+ a.push_back(readChar());
+ seek(cp);
+ return a;
+ }
+ llong s = size();
+ if (s < 0) return a;
+ a.resize(s);
+ s = readAll(a.data());
+ seek(cp);
+ if (s >= 0) a.resize(s);*/
+ return a;
+}
+
+
+llong PISharedMemory::size() const {
+ if (isClosed()) return -1;
+ return dsize;
+}
+
+
+int PISharedMemory::read(void * read_to, int max_size) {
+#ifdef WINDOWS
+ if (!PRIVATE->data) return -1;
+ CopyMemory(read_to, PRIVATE->data, max_size);
+ return max_size;
+#endif
+#ifdef LINUX
+ if (!PRIVATE->data) return -1;
+ memcpy(read_to, PRIVATE->data, max_size);
+ return max_size;
+#endif
+}
+
+
+int PISharedMemory::write(const void * data, int max_size) {
+#ifdef WINDOWS
+ if (!PRIVATE->data) return -1;
+ CopyMemory(PRIVATE->data, data, max_size);
+ return max_size;
+#endif
+#ifdef LINUX
+ if (!PRIVATE->data) return -1;
+ memcpy(PRIVATE->data, data, max_size);
+ return max_size;
+#endif
+}
diff --git a/src/io/pisharedmemory.h b/src/io/pisharedmemory.h
new file mode 100644
index 00000000..b26c1e5f
--- /dev/null
+++ b/src/io/pisharedmemory.h
@@ -0,0 +1,76 @@
+/*! \file pisharedmemory.h
+ * \brief Shared memory
+*/
+/*
+ PIP - Platform Independent Primitives
+ Shared Memory
+ Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef PISHAREDMEMORY_H
+#define PISHAREDMEMORY_H
+
+#include "piiodevice.h"
+
+
+class PIP_EXPORT PISharedMemory: public PIIODevice
+{
+ PIIODEVICE(PISharedMemory)
+public:
+
+ explicit PISharedMemory();
+
+ //! Constructs a shared memory object with name "shm_name", size "size" and open mode "mode"
+ explicit PISharedMemory(const PIString & shm_name, int size, DeviceMode mode = ReadWrite);
+
+ PISharedMemory(const PISharedMemory & other);
+
+ virtual ~PISharedMemory() {close();}
+
+ //! Read all shared memory object content to byte array and return it
+ PIByteArray readAll();
+
+ //! Returns shared memory object size
+ llong size() const;
+
+ //! Returns if shared memory object is empty
+ bool isEmpty() const {return (size() <= 0);}
+
+ //! Read from shared memory object to "read_to" no more than "max_size" and return readed bytes count
+ int read(void * read_to, int max_size);
+
+ //! Write to shared memory object "data" with size "max_size" and return written bytes count
+ int write(const void * data, int max_size);
+
+ //! Write "data" to shared memory object
+ int write(const PIByteArray & data) {return write(data.data(), data.size_s());}
+
+
+protected:
+ bool openDevice();
+ bool closeDevice();
+
+private:
+ void initPrivate();
+
+ int dsize;
+ PRIVATE_DECLARATION
+
+
+};
+
+
+#endif // PISHAREDMEMORY_H
diff --git a/src/system/pisingleapplication.cpp b/src/system/pisingleapplication.cpp
new file mode 100644
index 00000000..bedfb12e
--- /dev/null
+++ b/src/system/pisingleapplication.cpp
@@ -0,0 +1,104 @@
+/*
+ PIP - Platform Independent Primitives
+ Single application
+ Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "pisingleapplication.h"
+#include "pisharedmemory.h"
+
+#define SHM_SIZE 1024*32
+
+
+PISingleApplication::PISingleApplication(const PIString & app_name): PIThread() {
+ first = true;
+ started = false;
+ sacnt = 0;
+ shm = new PISharedMemory("sa_" + app_name, SHM_SIZE);
+ start(100);
+}
+
+
+PISingleApplication::~PISingleApplication() {
+ stop();
+ if (!waitForFinish(5000))
+ terminate();
+ delete shm;
+}
+
+
+bool PISingleApplication::isFirst() const {
+ waitFirst();
+ return first;
+}
+
+
+void PISingleApplication::sendMessage(const PIByteArray & m) {
+ waitFirst();
+ PIByteArray ba;
+ int lm[2] = {0, 0};
+ for (;;) {
+ shm->read(lm, 8);
+ if (lm[1] == 0) break;
+ piMSleep(10);
+ }
+ ba << sacnt << int(1) << m;
+ shm->write(ba);
+}
+
+
+void PISingleApplication::begin() {
+ int cnt[2] = {0, 0};
+ for (int i = 0; i < 5; ++i) {
+ cnt[1] = cnt[0];
+ shm->read(cnt, 4);
+ if (cnt[0] != cnt[1]) {
+ first = false;
+ break;
+ }
+ piMSleep(100);
+ }
+ //piCoutObj << "started" << first << shm->size();
+ readed.reserve(shm->size());
+ started = true;
+}
+
+
+void PISingleApplication::run() {
+ if (!first) return;
+ ++sacnt;
+ shm->write(&sacnt, 4);
+ //piCoutObj << "write" << sacnt;
+ readed = shm->readAll();
+ int t(0), nm(0);
+ readed >> t >> nm;
+ if (nm != 0) {
+ PIByteArray msg;
+ readed >> msg;
+ if (!msg.isEmpty()) {
+ messageReceived(msg);
+ //piCoutObj << "message" << msg;
+ }
+ int wi[2] = {sacnt, 0};
+ shm->write(wi, 8);
+ }
+}
+
+
+void PISingleApplication::waitFirst() const {
+ while (!started)
+ piMSleep(50);
+}
diff --git a/src/system/pisingleapplication.h b/src/system/pisingleapplication.h
new file mode 100644
index 00000000..80f45673
--- /dev/null
+++ b/src/system/pisingleapplication.h
@@ -0,0 +1,51 @@
+/*
+ PIP - Platform Independent Primitives
+ Single application
+ Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef PISINGLEAPPLICATION_H
+#define PISINGLEAPPLICATION_H
+
+#include "pithread.h"
+
+class PISharedMemory;
+
+class PIP_EXPORT PISingleApplication: protected PIThread {
+ PIOBJECT_SUBCLASS(PISingleApplication, PIThread)
+public:
+ PISingleApplication(const PIString & app_name = PIString());
+ ~PISingleApplication();
+
+ bool isFirst() const;
+
+ EVENT_HANDLER1(void, sendMessage, const PIByteArray &, m);
+ EVENT1(messageReceived, const PIByteArray &, m)
+
+private:
+ void begin();
+ void run();
+ void waitFirst() const;
+
+ PISharedMemory * shm;
+ PITimeMeasurer ftm;
+ PIByteArray readed;
+ bool first, started;
+ int sacnt;
+
+};
+
+#endif // PISINGLEAPPLICATION_H
diff --git a/src/system/pisystemmodule.h b/src/system/pisystemmodule.h
index e84a8753..01a9f154 100644
--- a/src/system/pisystemmodule.h
+++ b/src/system/pisystemmodule.h
@@ -27,5 +27,6 @@
#include "pisysteminfo.h"
#include "pisystemtests.h"
#include "pisystemmonitor.h"
+#include "pisingleapplication.h"
#endif // PISYSTEMMODULE_H
diff --git a/utils/system_daemon/main.cpp b/utils/system_daemon/main.cpp
index 379bb69c..09d86395 100755
--- a/utils/system_daemon/main.cpp
+++ b/utils/system_daemon/main.cpp
@@ -17,10 +17,11 @@
along with this program. If not, see .
*/
-#include "picli.h"
+#include "pisingleapplication.h"
#include "pisystemmonitor.h"
#include "pisysteminfo.h"
#include "piprocess.h"
+#include "picli.h"
#include "file_manager.h"
#include "daemon.h"
#include "shared.h"
@@ -285,14 +286,24 @@ int main(int argc, char * argv[]) {
cli.addArgument("help");
cli.addArgument("daemon");
cli.addArgument("force");
+ cli.addArgument("1");
cli.addArgument("name", true);
if (cli.hasArgument("help")) {
usage();
return 0;
}
PIString name = cli.argumentValue("name");
+ PISingleApplication * sapp = 0;
+ if (cli.hasArgument("1") && !cli.hasArgument("force")) {
+ sapp = new PISingleApplication("pisd");
+ if (!sapp->isFirst()) {
+ piCout << "Another pisd is running, exit";
+ return 0;
+ }
+ }
if (cli.hasArgument("daemon")) {
PIStringList args;
+ args << "-1";
if (cli.hasArgument("force"))
args << "-f";
if (!name.isEmpty())
@@ -314,5 +325,6 @@ int main(int argc, char * argv[]) {
delete menu;
delete daemon;
delete screen;
+ if (sapp) delete sapp;
return 0;
}
diff --git a/utils/system_daemon/shared.cpp b/utils/system_daemon/shared.cpp
index 28cd99ac..165ccf33 100644
--- a/utils/system_daemon/shared.cpp
+++ b/utils/system_daemon/shared.cpp
@@ -1,7 +1,7 @@
#include "shared.h"
#include "picrypt.h"
-extern PIScreen screen;
+extern PIScreen * screen;
class DlgWatcher: public PIThread {
@@ -56,9 +56,9 @@ PIString askUserInput(const PIString & desc) {
dlg.addTile(input);
dlg.addTile(btns);
DlgWatcher w;
- CONNECTU(&screen, keyPressed, &w, keyPressed)
- CONNECTU(&screen, tileEvent, &w, tileEvent)
- screen.setDialogTile(&dlg);
+ CONNECTU(screen, keyPressed, &w, keyPressed)
+ CONNECTU(screen, tileEvent, &w, tileEvent)
+ screen->setDialogTile(&dlg);
while (!w.close) {
PIKbdListener::instance()->readKeyboard();
piMSleep(10);
@@ -83,9 +83,9 @@ bool askQuestion(const PIString & t) {
dlg.addTile(lbl);
dlg.addTile(btns);
DlgWatcher w;
- CONNECTU(&screen, keyPressed, &w, keyPressed)
- CONNECTU(&screen, tileEvent, &w, tileEvent)
- screen.setDialogTile(&dlg);
+ CONNECTU(screen, keyPressed, &w, keyPressed)
+ CONNECTU(screen, tileEvent, &w, tileEvent)
+ screen->setDialogTile(&dlg);
while (!w.close) {
PIKbdListener::instance()->readKeyboard();
piMSleep(10);
@@ -108,9 +108,9 @@ void showInfo(const PIString & t) {
dlg.addTile(lbl);
dlg.addTile(btns);
DlgWatcher w;
- CONNECTU(&screen, keyPressed, &w, keyPressed)
- CONNECTU(&screen, tileEvent, &w, tileEvent)
- screen.setDialogTile(&dlg);
+ CONNECTU(screen, keyPressed, &w, keyPressed)
+ CONNECTU(screen, tileEvent, &w, tileEvent)
+ screen->setDialogTile(&dlg);
while (!w.close) {
PIKbdListener::instance()->readKeyboard();
piMSleep(10);