rhodes 1.5.4 → 1.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. data/Manifest.txt +11 -1
  2. data/Rakefile +1 -1
  3. data/lib/extensions/digest/ext/Rakefile +11 -6
  4. data/lib/extensions/digest/ext/build.bat +2 -0
  5. data/lib/extensions/uri/uri.rb +29 -0
  6. data/lib/extensions/uri/uri/common.rb +727 -0
  7. data/lib/extensions/uri/uri/ftp.rb +198 -0
  8. data/lib/extensions/uri/uri/generic.rb +1128 -0
  9. data/lib/extensions/uri/uri/http.rb +100 -0
  10. data/lib/extensions/uri/uri/https.rb +20 -0
  11. data/lib/extensions/uri/uri/ldap.rb +190 -0
  12. data/lib/extensions/uri/uri/ldaps.rb +12 -0
  13. data/lib/extensions/uri/uri/mailto.rb +266 -0
  14. data/lib/framework/rhodes.rb +2 -2
  15. data/lib/framework/rhom/rhom_db_adapter.rb +12 -26
  16. data/lib/framework/rhom/rhom_object_factory.rb +8 -1
  17. data/lib/framework/version.rb +2 -2
  18. data/lib/rhodes.rb +2 -2
  19. data/platform/android/Rhodes/AndroidManifest.xml +2 -2
  20. data/platform/android/Rhodes/src/com/rhomobile/rhodes/Rhodes.java +87 -42
  21. data/platform/android/Rhodes/src/com/rhomobile/rhodes/SplashScreen.java +58 -7
  22. data/platform/android/Rhodes/src/com/rhomobile/rhodes/mainview/MainView.java +2 -0
  23. data/platform/android/Rhodes/src/com/rhomobile/rhodes/mainview/SimpleMainView.java +35 -19
  24. data/platform/android/Rhodes/src/com/rhomobile/rhodes/mainview/TabbedMainView.java +4 -0
  25. data/platform/android/build/android.rake +30 -25
  26. data/platform/bb/build/rhodes_build.files +1 -1
  27. data/platform/bb/rhodes/rhodes.jdp +1 -1
  28. data/platform/bb/rhodes/src/com/rho/RhoRubyHelper.java +1 -1
  29. data/platform/bb/rhodes/src/com/rho/rubyext/Alert.java +300 -0
  30. data/platform/bb/rhodes/src/com/rho/rubyext/GeoLocation.java +42 -5
  31. data/platform/bb/rhodes/src/rhomobile/PushListeningThread.java +3 -4
  32. data/platform/bb/rhodes/src/rhomobile/RhodesApplication.java +33 -107
  33. data/platform/iphone/Classes/RhoRunnerAppDelegate.m +2 -0
  34. data/platform/iphone/Info.plist +1 -1
  35. data/platform/iphone/rbuild/iphone.rake +1 -1
  36. data/platform/iphone/rhoextlib/rhoextlib.xcodeproj/project.pbxproj +4 -0
  37. data/platform/shared/common/RhoMutexLock.h +8 -1
  38. data/platform/shared/common/RhodesApp.cpp +1 -1
  39. data/platform/shared/db/DBAdapter.cpp +77 -8
  40. data/platform/shared/db/DBAdapter.h +24 -9
  41. data/platform/shared/db/DBResult.cpp +19 -0
  42. data/platform/shared/db/DBResult.h +7 -5
  43. data/platform/shared/net/HttpServer.cpp +2 -0
  44. data/platform/shared/ruby/ext/rho/rhoruby.c +55 -0
  45. data/platform/shared/ruby/ext/rho/rhoruby.h +9 -0
  46. data/platform/shared/ruby/ext/rho/rhosupport.c +13 -4
  47. data/platform/shared/ruby/ext/sqlite3_api/sqlite3_api_wrap.c +21 -0
  48. data/platform/shared/ruby/thread_pthread.c +4 -4
  49. data/platform/shared/ruby/thread_win32.c +4 -4
  50. data/platform/shared/rubyJVM/src/com/rho/RhodesApp.java +19 -1
  51. data/platform/shared/rubyJVM/src/com/rho/db/DBAdapter.java +57 -24
  52. data/platform/shared/rubyJVM/src/com/rho/net/NetRequest.java +6 -1
  53. data/platform/shared/rubyJVM/src/com/rho/sync/SyncSource.java +2 -2
  54. data/platform/shared/rubyJVM/src/com/rho/sync/SyncThread.java +5 -5
  55. data/platform/shared/sync/SyncSource.cpp +1 -1
  56. data/platform/shared/sync/SyncThread.cpp +6 -9
  57. data/platform/wm/rhodes/Rhodes.cpp +4 -0
  58. data/rakefile.rb +1 -1
  59. metadata +13 -3
  60. data/platform/bb/rhodes/src/rhomobile/Alert.java +0 -65
@@ -49,23 +49,24 @@ public class GeoLocation extends RhoThread{
49
49
  try{
50
50
  if ( location == null )
51
51
  {
52
- LOG.TRACE("GetLocation - locationUpdated: location is null.");
52
+ LOG.TRACE("locationUpdated: location is null.");
53
53
  return;
54
54
  }
55
55
 
56
56
  if( !location.isValid() )
57
57
  {
58
- LOG.TRACE("GetLocation - locationUpdated: location invalid.");
58
+ String strExtraInfo = location.getExtraInfo("text/plain");
59
+ LOG.TRACE("locationUpdated: location invalid.Extra info: " + (strExtraInfo!=null ? strExtraInfo :"") );
59
60
  return;
60
61
  }
61
62
 
62
63
  coord = location.getQualifiedCoordinates();
63
64
  if(coord != null )
64
65
  {
65
- LOG.TRACE("GetLocation - latitude: " + Double.toString(m_parent.m_lat));
66
- LOG.TRACE("GetLocation - longitude: " + Double.toString(m_parent.m_lon));
66
+ LOG.TRACE("locationUpdated - latitude: " + Double.toString(coord.getLatitude()));
67
+ LOG.TRACE("locationUpdated - longitude: " + Double.toString(coord.getLongitude()));
67
68
  }else
68
- LOG.TRACE("GetLocation - getQualifiedCoordinates: return null.");
69
+ LOG.TRACE("locationUpdated - getQualifiedCoordinates: return null.");
69
70
 
70
71
  }catch(Exception exc)
71
72
  {
@@ -212,6 +213,8 @@ public class GeoLocation extends RhoThread{
212
213
  {
213
214
  if (bErrorNotify)
214
215
  onLocationError();
216
+ else
217
+ checkKnownPosition();
215
218
  }
216
219
  }
217
220
  }
@@ -295,6 +298,40 @@ public class GeoLocation extends RhoThread{
295
298
  }
296
299
  }
297
300
 
301
+ void checkKnownPosition()
302
+ {
303
+ synchronized(sync)
304
+ {
305
+ if ( m_bDetermined )
306
+ return;
307
+
308
+ try{
309
+ Location location = LocationProvider.getLastKnownLocation();
310
+ if ( location != null && location.isValid() )
311
+ {
312
+ long locTime = location.getTimestamp();
313
+ long curTime = java.lang.System.currentTimeMillis();
314
+ long ageInMitutes = (curTime - locTime)/60000;
315
+ LOG.TRACE("getLastKnownLocation return valid location. Age in minutes from now: " + ageInMitutes);
316
+ Coordinates coord = location.getQualifiedCoordinates();
317
+ if(coord != null )
318
+ {
319
+ LOG.TRACE("getLastKnownLocation - latitude: " + Double.toString(coord.getLatitude()));
320
+ LOG.TRACE("getLastKnownLocation - longitude: " + Double.toString(coord.getLongitude()));
321
+
322
+ if ( ageInMitutes <= 10 )
323
+ updateLocation(coord.getLatitude(), coord.getLongitude());
324
+ }else
325
+ LOG.TRACE("getLastKnownLocation - getQualifiedCoordinates: return null.");
326
+ }
327
+ }catch(Exception exc)
328
+ {
329
+ LOG.ERROR("getLastKnownLocation failed.", exc);
330
+ }
331
+ }
332
+
333
+ }
334
+
298
335
  private void updateLocation( double dLatitude, double dLongitude )
299
336
  {
300
337
  synchronized(sync)
@@ -10,7 +10,6 @@ import com.rho.RhoLogger;
10
10
  import com.rho.sync.SyncThread;
11
11
  import com.rho.RhoConf;
12
12
 
13
- import net.rim.device.api.system.*;
14
13
  import net.rim.device.api.util.*;
15
14
  import net.rim.device.api.io.http.*;
16
15
 
@@ -208,15 +207,15 @@ public class PushListeningThread extends Thread {
208
207
  }
209
208
 
210
209
  private void showPopup(String message) {
211
- RhodesApplication.getInstance().showPopup(message);
210
+ com.rho.rubyext.Alert.showPopup(message);
212
211
  }
213
212
 
214
213
  private void vibrate(String duration) {
215
- RhodesApplication.getInstance().vibrate(duration);
214
+ com.rho.rubyext.Alert.vibrate(duration);
216
215
  }
217
216
 
218
217
  private void play_file(String file_name, String media_type) {
219
- RhodesApplication.getInstance().play_file(file_name, media_type);
218
+ com.rho.rubyext.Alert.play_file(file_name, media_type);
220
219
  }
221
220
 
222
221
  private void processPushMessage(final byte[] data, int nLen)
@@ -295,17 +295,29 @@ final public class RhodesApplication extends UiApplication implements RenderingA
295
295
  return false;
296
296
  }
297
297
 
298
- void back(){
298
+ void back()
299
+ {
299
300
  String url = m_strAppBackUrl;
300
301
  if ( url.length() == 0)
301
302
  {
302
303
  if ( _history.size() <= 1 )
304
+ {
305
+ if ( RhoConf.getInstance().getBool("bb_disable_closebyback"))
306
+ return;
307
+
308
+ this._mainScreen.close();
303
309
  return;
304
-
310
+ }
311
+
305
312
  int nPos = _history.size()-2;
306
313
  url = (String)_history.elementAt(nPos);
307
314
  _history.removeElementAt(nPos+1);
308
- }else
315
+ }else if ( url.equalsIgnoreCase("close"))
316
+ {
317
+ this._mainScreen.close();
318
+ return;
319
+ }
320
+ else
309
321
  addToHistory(url,null);
310
322
 
311
323
  saveCurrentLocation(url);
@@ -410,99 +422,6 @@ final public class RhodesApplication extends UiApplication implements RenderingA
410
422
 
411
423
  return false;
412
424
  }
413
-
414
- public void showPopup(final String message) {
415
- Application.getApplication().invokeLater(new Runnable() {
416
- public void run() {
417
- String[] choices = { "Ok" };
418
- requestForeground();
419
- Dialog.ask(message,choices,0);
420
- }
421
- });
422
- }
423
-
424
- public void vibrate(final String duration) {
425
- Application.getApplication().invokeLater(new Runnable() {
426
- public void run() {
427
- int dt = 2500;
428
- try {
429
- dt = Integer.parseInt(duration);
430
- } catch (NumberFormatException e) {
431
- }
432
-
433
- if (dt > 25500) dt = 25500;
434
-
435
- if (dt > 0) {
436
- Alert.startVibrate(dt);
437
- }
438
- }
439
- });
440
- }
441
-
442
- private static final String[][] filetypes = { {"mp3", "audio/mpeg"}, {"wav","audio/x-wav"} };
443
- private String getTypeFromExt(String file_name) {
444
- int pt = file_name.lastIndexOf('.');
445
- if (pt<0) {
446
- return filetypes[0][1];
447
- }
448
- String ext = file_name.substring(pt+1);
449
- for (int cnt = filetypes.length - 1; cnt >= 0; --cnt) {
450
- if(filetypes[cnt][0].equals(ext)) {
451
- return filetypes[cnt][1];
452
- }
453
- }
454
- return null;
455
- }
456
-
457
- public void play_file(final String file_name, final String media_type) {
458
- Application.getApplication().invokeLater(new Runnable() {
459
- public void run() {
460
- String type = media_type == null ? getTypeFromExt(file_name) : media_type;
461
- if (type != null) {
462
- LOG.INFO("File type: " + type);
463
- } else {
464
- LOG.ERROR("Error - can't play unknown file type");
465
- return;
466
- }
467
-
468
- String types[] =
469
- javax.microedition.media.Manager.getSupportedContentTypes(null);
470
- for (int cnt = types.length - 1; cnt >= 0; --cnt) {
471
- if (type.equals(types[cnt])) {
472
- LOG.INFO( "Playing file " + file_name + " of type: " + types[cnt]);
473
-
474
- SimpleFile file = null;
475
- try {
476
- //retrieve the file
477
- Class clazz = Class.forName("rhomobile.RhodesApplication");
478
- file = RhoClassFactory.createFile();
479
- String strClassName = file_name;
480
- if ( !strClassName.startsWith("/apps") )
481
- strClassName = "/apps" + file_name;
482
-
483
- InputStream is = file.getResourceAsStream(clazz.getClass(), strClassName);
484
- //create an instance of the player from the InputStream
485
- Player player = javax.microedition.media.Manager.createPlayer(is,type);
486
- player.realize();
487
- player.prefetch();
488
- //start the player
489
- player.start();
490
- } catch (Exception ex) {
491
- LOG.ERROR("Error playing " + file_name + " :" + ex.getMessage());
492
- } finally {
493
- try{
494
- if ( file != null )
495
- file.close();
496
- }catch(Exception exc){}
497
- }
498
- return;
499
- }
500
- }
501
-
502
- LOG.ERROR("Error - media type " + type + " isn't supported.");
503
- }
504
- });
505
- }
506
425
 
507
426
  private static final String REFERER = "referer";
508
427
 
@@ -974,15 +893,17 @@ final public class RhodesApplication extends UiApplication implements RenderingA
974
893
  } else {
975
894
  if ( label.equalsIgnoreCase("back") )
976
895
  m_strAppBackUrl = value;
977
-
978
- MenuItem itemToAdd = new MenuItem(label, 200000, 10) {
979
- public void run() {
980
- String val = getPathForMenuItem(value);
981
- addToHistory(val, null );
982
- navigateUrl(val);
983
- }
984
- };
985
- menuItems.addElement(itemToAdd);
896
+ else
897
+ {
898
+ MenuItem itemToAdd = new MenuItem(label, 200000, 10) {
899
+ public void run() {
900
+ String val = getPathForMenuItem(value);
901
+ addToHistory(val, null );
902
+ navigateUrl(val);
903
+ }
904
+ };
905
+ menuItems.addElement(itemToAdd);
906
+ }
986
907
  }
987
908
  }
988
909
 
@@ -1063,7 +984,7 @@ final public class RhodesApplication extends UiApplication implements RenderingA
1063
984
  if (splash.isFlag(SplashScreen.VCENTER) )
1064
985
  nFlags |= Field.FIELD_VCENTER;
1065
986
 
1066
- int scaleX = 1, scaleY = 1;
987
+ int scaleX = 65536, scaleY = 65536;
1067
988
  int currentWidthFixed32 = Fixed32.toFP(img.getWidth());
1068
989
  int currentHeightFixed32 = Fixed32.toFP(img.getHeight());
1069
990
  int screenWidthFixed32 = Fixed32.toFP(Display.getWidth());
@@ -1071,11 +992,16 @@ final public class RhodesApplication extends UiApplication implements RenderingA
1071
992
 
1072
993
  if (splash.isFlag(SplashScreen.VZOOM) )
1073
994
  scaleY = Fixed32.div(currentHeightFixed32, screenHeightFixed32);
995
+ else
996
+ scaleY = Fixed32.div(currentHeightFixed32, currentHeightFixed32);
997
+
1074
998
  if (splash.isFlag(SplashScreen.HZOOM) )
1075
999
  scaleX = Fixed32.div(currentWidthFixed32, screenWidthFixed32);
1000
+ else
1001
+ scaleX = Fixed32.div(currentWidthFixed32, currentWidthFixed32);
1076
1002
 
1077
1003
  EncodedImage img2 = img;
1078
- if ( scaleX != 1 || scaleY != 1)
1004
+ if ( scaleX != 65536 || scaleY != 65536)
1079
1005
  img2 = img.scaleImage32(scaleX, scaleY);
1080
1006
  Bitmap bitmap = img2.getBitmap();
1081
1007
 
@@ -453,6 +453,8 @@
453
453
  appStarted = false;
454
454
  splashDisplayed = false;
455
455
 
456
+ [NSThread setThreadPriority:1.0];
457
+
456
458
  //Create local server and start it
457
459
  //serverHost = [[ServerHost alloc] init];
458
460
  serverHost = [ServerHost sharedInstance];
@@ -21,7 +21,7 @@
21
21
  <key>CFBundleSignature</key>
22
22
  <string>????</string>
23
23
  <key>CFBundleVersion</key>
24
- <string>1.5.4</string>
24
+ <string>1.5.5</string>
25
25
  <key>LSRequiresIPhoneOS</key>
26
26
  <true/>
27
27
  </dict>
@@ -132,6 +132,7 @@ namespace "build" do
132
132
 
133
133
  ENV["ARCHS"] ||= simulator ? "i386" : "armv6"
134
134
 
135
+ ENV['RHO_ROOT'] = $startdir
135
136
 
136
137
  $app_config["extensions"].each do |ext|
137
138
  rhoextpath = "lib/extensions/" + ext + "/ext"
@@ -147,7 +148,6 @@ namespace "build" do
147
148
  extpath = rhoextpath
148
149
  end
149
150
 
150
-
151
151
  puts Jake.run('./build', [], extpath) if File.executable? File.join(extpath, 'build')
152
152
  exit 1 unless $? == 0
153
153
 
@@ -170,8 +170,12 @@
170
170
  GCC_MODEL_TUNING = G5;
171
171
  GCC_PRECOMPILE_PREFIX_HEADER = YES;
172
172
  GCC_PREFIX_HEADER = rhoextlib_Prefix.pch;
173
+ GCC_VERSION = 4.2;
173
174
  INSTALL_PATH = /usr/local/lib;
175
+ OTHER_LDFLAGS = "";
174
176
  PRODUCT_NAME = rhoextlib;
177
+ SDKROOT = iphonesimulator3.0;
178
+ VALID_ARCHS = armv6;
175
179
  };
176
180
  name = Release;
177
181
  };
@@ -86,7 +86,14 @@ private:
86
86
  static int __g_mutex_init_##name = 0;\
87
87
  pthread_mutex_t __g_mutex_##name = PTHREAD_MUTEX_INITIALIZER;
88
88
 
89
- #define RHO_LOCK(name) {if(!__g_mutex_init_##name){pthread_mutex_init(&__g_mutex_##name, NULL);__g_mutex_init_##name=1;} pthread_mutex_lock(&__g_mutex_##name);}
89
+ #define RHO_LOCK(name) {if(!__g_mutex_init_##name){\
90
+ pthread_mutexattr_t attr;\
91
+ pthread_mutexattr_init(&attr);\
92
+ pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);\
93
+ pthread_mutex_init(&__g_mutex_##name, &attr);\
94
+ pthread_mutexattr_destroy(&attr);\
95
+ __g_mutex_init_##name=1;\
96
+ } pthread_mutex_lock(&__g_mutex_##name);}
90
97
  #define RHO_UNLOCK(name) pthread_mutex_unlock(&__g_mutex_##name);
91
98
 
92
99
  #else
@@ -614,7 +614,7 @@ String CRhodesApp::addCallbackObject(ICallbackObject* pCallbackObject, String st
614
614
 
615
615
  unsigned long CRhodesApp::getCallbackObject(int nIndex)
616
616
  {
617
- if ( nIndex < 0 || nIndex > m_arCallbackObjects.size() )
617
+ if ( nIndex < 0 || nIndex > (int)m_arCallbackObjects.size() )
618
618
  return rho_ruby_get_NIL();
619
619
 
620
620
  ICallbackObject* pCallbackObject = m_arCallbackObjects.elementAt(nIndex);
@@ -5,6 +5,7 @@
5
5
  #include "common/RhoFilePath.h"
6
6
  #include "common/RhoConf.h"
7
7
  #include "common/RhodesApp.h"
8
+ #include "ruby/ext/rho/rhoruby.h"
8
9
 
9
10
  namespace rho{
10
11
  namespace db{
@@ -498,9 +499,9 @@ void CDBAdapter::close()
498
499
  DBResultPtr CDBAdapter::prepareStatement( const char* szSt )
499
500
  {
500
501
  if ( m_dbHandle == null )
501
- return new CDBResult(m_mxDB);
502
+ return new CDBResult();
502
503
 
503
- DBResultPtr res = new CDBResult(0,m_bInsideTransaction ? m_mxTransDB : m_mxDB);
504
+ DBResultPtr res = new CDBResult(0,this);
504
505
  sqlite3_stmt* st = m_mapStatements.get(szSt);
505
506
  if ( st != null )
506
507
  {
@@ -547,13 +548,32 @@ DBResultPtr CDBAdapter::executeStatement(DBResultPtr& res)
547
548
  return res;
548
549
  }
549
550
 
551
+ void CDBAdapter::Lock()
552
+ {
553
+ if ( m_mxRuby.isMainRubyThread() )
554
+ m_bUIWaitDB = true;
555
+
556
+ m_mxRuby.Lock();
557
+ m_mxDB.Lock();
558
+
559
+ if ( m_mxRuby.isMainRubyThread() )
560
+ m_bUIWaitDB = false;
561
+ }
562
+
563
+ void CDBAdapter::Unlock()
564
+ {
565
+ m_mxDB.Unlock();
566
+ m_mxRuby.Unlock();
567
+ }
568
+
550
569
  void CDBAdapter::startTransaction()
551
570
  {
552
571
  Lock();
553
- m_bInsideTransaction=true;
572
+ m_nTransactionCounter++;
573
+
554
574
  char *zErr = 0;
555
575
  int rc = 0;
556
- if ( m_dbHandle )
576
+ if ( m_dbHandle && m_nTransactionCounter == 1)
557
577
  {
558
578
  rc = sqlite3_exec(m_dbHandle, "BEGIN IMMEDIATE;",0,0,&zErr);
559
579
  checkDbError(rc);
@@ -565,14 +585,14 @@ void CDBAdapter::endTransaction()
565
585
  char *zErr = 0;
566
586
  int rc = 0;
567
587
 
568
- if (m_dbHandle)
588
+ m_nTransactionCounter--;
589
+ if (m_dbHandle && m_nTransactionCounter == 0)
569
590
  {
570
591
  getAttrMgr().save(*this);
571
592
  rc = sqlite3_exec(m_dbHandle, "END;",0,0,&zErr);
572
593
  checkDbError(rc);
573
594
  }
574
595
 
575
- m_bInsideTransaction=false;
576
596
  Unlock();
577
597
  }
578
598
 
@@ -580,15 +600,64 @@ void CDBAdapter::rollback()
580
600
  {
581
601
  char *zErr = 0;
582
602
  int rc = 0;
583
- if (m_dbHandle)
603
+
604
+ m_nTransactionCounter--;
605
+ if (m_dbHandle && m_nTransactionCounter == 0)
584
606
  {
585
607
  rc = sqlite3_exec(m_dbHandle, "ROLLBACK;",0,0,&zErr);
586
608
  checkDbError(rc);
587
609
  }
588
610
 
589
- m_bInsideTransaction=false;
590
611
  Unlock();
591
612
  }
592
613
 
593
614
  }
594
615
  }
616
+
617
+ namespace rho{
618
+ namespace common{
619
+
620
+ CRubyMutex::CRubyMutex() : m_nLockCount(0), m_valThread(0), m_valMutex(null)
621
+ {
622
+ }
623
+
624
+ CRubyMutex::~CRubyMutex()
625
+ {
626
+ rho_ruby_destroy_mutex(m_valMutex);
627
+ }
628
+
629
+ boolean CRubyMutex::isMainRubyThread()
630
+ {
631
+ return rho_ruby_main_thread() == rho_ruby_current_thread();
632
+ }
633
+
634
+ void CRubyMutex::Lock()
635
+ {
636
+ unsigned long curThread = rho_ruby_current_thread();
637
+ if ( curThread == null )
638
+ return;
639
+
640
+ if ( m_valThread != curThread )
641
+ {
642
+ if ( m_valMutex == null )
643
+ m_valMutex = rho_ruby_create_mutex();
644
+
645
+ rho_ruby_lock_mutex(m_valMutex);
646
+ m_valThread = curThread;
647
+ m_nLockCount = 1;
648
+ }else
649
+ m_nLockCount += 1;
650
+ }
651
+
652
+ void CRubyMutex::Unlock()
653
+ {
654
+ m_nLockCount--;
655
+ if ( m_nLockCount == 0 )
656
+ {
657
+ m_valThread = null;
658
+ rho_ruby_unlock_mutex(m_valMutex);
659
+ }
660
+ }
661
+
662
+ }
663
+ }