mscanf in a callback fixed 44/17044/3
Cedric Delamarre [Mon, 17 Aug 2015 15:46:41 +0000 (17:46 +0200)]
function demo_1()
    my_handle = scf(100001);
    plot(1:10)
    if is_handle_valid(my_handle) then
        mprintf("Press Return to continue");
        mscanf("%c");
    end
    plot(1:20)
endfunction

f = figure();
h = uicontrol(f, "style", "pushbutton", "string", "Lancer demo", "position", [20 20 100 50], "callback", "demo_1()");

Change-Id: Ia20ae93a63b971c433146b653b35813f8d1324ab

scilab/modules/ast/includes/system_env/configvariable.hxx
scilab/modules/ast/includes/system_env/threadmanagement.hxx
scilab/modules/ast/src/cpp/system_env/configvariable.cpp
scilab/modules/ast/src/cpp/system_env/threadmanagement.cpp
scilab/modules/console/src/cpp/scilabRead.cpp
scilab/modules/core/src/cpp/InitScilab.cpp
scilab/modules/fileio/sci_gateway/cpp/sci_mscanf.cpp

index 8315210..ded5bf5 100644 (file)
@@ -444,6 +444,20 @@ public:
     static void setExecutedFileID(int _iFileID);
     static int getExecutedFileID();
 
+    // string read from console by scilabRead
+private:
+    static char* m_pcConsoleReadStr;
+public:
+    static void setConsoleReadStr(char* _pcConsoleReadStr);
+    static char* getConsoleReadStr();
+
+    // tell if the command return by scilabRead is a scilab command or not
+private:
+    static int m_isScilabCommand;
+public:
+    static void setScilabCommand(int _isciCmd);
+    static int isScilabCommand();
+
 };
 
 #endif /* !__CONFIGVARIABLE_HXX__ */
index 86becb0..fd2c603 100644 (file)
@@ -28,6 +28,7 @@ private :
     static __threadLock m_RunnerLock;
     static __threadLock m_ParseLock;
     static __threadLock m_StoreCommandLock;
+    static __threadLock m_ScilabReadLock;
 
     static __threadSignal m_ConsoleExecDone;
     static __threadSignalLock m_ConsoleExecDoneLock;
@@ -70,6 +71,8 @@ public :
     static void UnlockStoreCommand(void);
     static void LockRunner(void);
     static void UnlockRunner(void);
+    static void LockScilabRead(void);
+    static void UnlockScilabRead(void);
 
     static void SendAvailableRunnerSignal(void);
     static void WaitForAvailableRunnerSignal(void);
index 7e4e66f..ca0e64a 100644 (file)
@@ -1402,3 +1402,44 @@ int ConfigVariable::getExecutedFileID()
 {
     return m_iFileID;
 }
+
+/*
+** string read from console by scilabRead
+** \{
+*/
+char* ConfigVariable::m_pcConsoleReadStr = NULL;
+void ConfigVariable::setConsoleReadStr(char* _pcConsoleReadStr)
+{
+    m_pcConsoleReadStr = _pcConsoleReadStr;
+}
+
+char* ConfigVariable::getConsoleReadStr()
+{
+    ThreadManagement::LockScilabRead();
+    char* tmp = m_pcConsoleReadStr;
+    m_pcConsoleReadStr = NULL;
+    ThreadManagement::UnlockScilabRead();
+    return tmp;
+}
+/*
+** \}
+*/
+
+/*
+** Tell to the console thread if the scilabRead return
+** is a scilab command or not.
+** \{
+*/
+int ConfigVariable::m_isScilabCommand = 1;
+void ConfigVariable::setScilabCommand(int _isciCmd)
+{
+    m_isScilabCommand = _isciCmd;
+}
+
+int ConfigVariable::isScilabCommand()
+{
+    return m_isScilabCommand;
+}
+/*
+** \}
+*/
index 8cf0992..e599862 100644 (file)
@@ -26,6 +26,7 @@ __threadKey ThreadManagement::m_tkConsole;
 __threadLock ThreadManagement::m_RunnerLock;
 __threadLock ThreadManagement::m_ParseLock;
 __threadLock ThreadManagement::m_StoreCommandLock;
+__threadLock ThreadManagement::m_ScilabReadLock;
 
 __threadSignal ThreadManagement::m_ConsoleExecDone;
 __threadSignalLock ThreadManagement::m_ConsoleExecDoneLock;
@@ -57,6 +58,7 @@ void ThreadManagement::initialize()
     __InitLock(&m_RunnerLock);
     __InitLock(&m_ParseLock);
     __InitLock(&m_StoreCommandLock);
+    __InitLock(&m_ScilabReadLock);
 
     __InitSignal(&m_AwakeRunner);
     __InitSignalLock(&m_AwakeRunnerLock);
@@ -138,6 +140,27 @@ void ThreadManagement::UnlockRunner(void)
 }
 
 /***
+    [ScilabRead Lock]
+    Used to manage scilabRead output wich can be used by Console thread or
+    main thread through mscanf function.
+***/
+void ThreadManagement::LockScilabRead(void)
+{
+#ifdef DEBUG_THREAD
+    PrintDebug("LockScilabRead");
+#endif // DEBUG_THREAD
+    __Lock(&m_ScilabReadLock);
+}
+
+void ThreadManagement::UnlockScilabRead(void)
+{
+#ifdef DEBUG_THREAD
+    PrintDebug("UnlockScilabRead");
+#endif // DEBUG_THREAD
+    __UnLock(&m_ScilabReadLock);
+}
+
+/***
     [AvailableRunner Signal]
 
     Send : The global Runner is available to store a new one.
index dff392b..f493dac 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include "configvariable.hxx"
+#include "threadmanagement.hxx"
 
 extern "C"
 {
@@ -43,6 +44,7 @@ void C2F(scilabread)(char* strRead, int len)
 
 char *scilabRead()
 {
+    ThreadManagement::LockScilabRead();
     if (getScilabMode() == SCILAB_STD)
     {
         /* Send new prompt to Java Console, do not display it */
@@ -73,5 +75,8 @@ char *scilabRead()
     diaryWriteln(pwstIn, TRUE);
     FREE(pwstIn);
 
+    ConfigVariable::setConsoleReadStr(pstTemp);
+    ThreadManagement::UnlockScilabRead();
+
     return pstTemp;
 }
index 88aaa2e..15e8fe1 100644 (file)
@@ -560,9 +560,6 @@ void* scilabReadAndExecCommand(void* param)
 //Thread used to parse and set console commands in storeCommand
 void* scilabReadAndStore(void* param)
 {
-    //    ThreadManagement::LockStart();
-    //    ThreadManagement::UnlockStart();
-
     Parser::ControlStatus controlStatus = Parser::AllControlClosed;
 
     char *command = NULL;
@@ -613,8 +610,17 @@ void* scilabReadAndStore(void* param)
             //set prompt value
             C2F(setprlev) (&pause);
 
-            char *pstRead = scilabRead();
+            ConfigVariable::setScilabCommand(1);
+            scilabRead();
+            if (ConfigVariable::isScilabCommand() == 0)
+            {
+                // happens when the return of scilabRead is used
+                // in other thread (ie: call mscanf in a callback)
+                ThreadManagement::WaitForConsoleExecDoneSignal();
+                continue;
+            }
 
+            char* pstRead = ConfigVariable::getConsoleReadStr();
             if (command == NULL)
             {
                 command = pstRead;
index cebaed7..978011f 100644 (file)
@@ -19,6 +19,8 @@
 #include "cell.hxx"
 #include "function.hxx"
 #include "double.hxx"
+#include "configvariable.hxx"
+#include "threadmanagement.hxx"
 
 extern "C"
 {
@@ -83,9 +85,25 @@ types::Function::ReturnValue sci_mscanf(types::typed_list &in, int _iRetCount, t
         {
             break;
         }
+
         // get data
-        wcsRead = to_wide_string(scilabRead());
+        // mscanf is called from a callback
+        ConfigVariable::setScilabCommand(0);
+        char* pcConsoleReadStr = ConfigVariable::getConsoleReadStr();
+        if (pcConsoleReadStr)
+        {
+            ThreadManagement::SendConsoleExecDoneSignal();
+        }
+        else // mscanf is called from the console
+        {
+            scilabRead();
+            pcConsoleReadStr = ConfigVariable::getConsoleReadStr();
+        }
+
+        wcsRead = to_wide_string(pcConsoleReadStr);
+        FREE(pcConsoleReadStr);
         int err = do_xxscanf(L"sscanf", (FILE *)0, wcsFormat, &args, wcsRead, &retval, buf, type);
+        FREE(wcsRead);
         if (err < 0)
         {
             return types::Function::Error;
@@ -115,7 +133,6 @@ types::Function::ReturnValue sci_mscanf(types::typed_list &in, int _iRetCount, t
                 break;
             }
         }
-        FREE(wcsRead);
     }
 
     unsigned int uiFormatUsed = 0;