1 /*----------------------------------------------------------------------------
2 ChucK Concurrent, On-the-fly Audio Programming Language
3 Compiler and Virtual Machine
5 Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6 http://chuck.cs.princeton.edu/
7 http://soundlab.cs.princeton.edu/
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 -----------------------------------------------------------------------------*/
25 //-----------------------------------------------------------------------------
29 // author: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
31 // Ananya Misra (amisra@cs.princeton.edu)
33 //-----------------------------------------------------------------------------
35 #include "chuck_type.h"
37 #include "chuck_instr.h"
38 #include "chuck_errmsg.h"
47 t_CKBOOL
Chuck_VM_Object::our_locks_in_effect
= TRUE
;
48 const t_CKINT
Chuck_IO::READ
= 0x1;
49 const t_CKINT
Chuck_IO::WRITE
= 0x2;
50 const t_CKINT
Chuck_IO::APPEND
= 0x4;
51 const t_CKINT
Chuck_IO::TRUNCATE
= 0x8;
52 const t_CKINT
Chuck_IO::ASCII
= 0x10;
53 const t_CKINT
Chuck_IO::BINARY
= 0x20;
58 //-----------------------------------------------------------------------------
60 // desc: initialize vm object
61 //-----------------------------------------------------------------------------
62 void Chuck_VM_Object::init_ref()
64 // set reference count
72 // add to vm allocator
73 // Chuck_VM_Alloc::instance()->add_object( this );
79 //-----------------------------------------------------------------------------
81 // desc: add reference
82 //-----------------------------------------------------------------------------
83 void Chuck_VM_Object::add_ref()
85 // increment reference count
88 // if going from 0 to 1
89 if( m_ref_count
== 1 )
91 // add to vm allocator
92 Chuck_VM_Alloc::instance()->add_object( this );
99 //-----------------------------------------------------------------------------
101 // desc: remove reference
102 //-----------------------------------------------------------------------------
103 void Chuck_VM_Object::release()
105 // make sure there is at least one reference
106 assert( m_ref_count
> 0 );
110 // if no more references
111 if( m_ref_count
== 0 )
114 if( our_locks_in_effect
&& m_locked
)
116 EM_error2( 0, "internal error: releasing locked VM object!" );
119 // in case assert is disabled
123 // tell the object manager to set this free
124 Chuck_VM_Alloc::instance()->free_object( this );
131 //-----------------------------------------------------------------------------
133 // desc: lock to keep from deleted
134 //-----------------------------------------------------------------------------
135 void Chuck_VM_Object::lock()
143 //-----------------------------------------------------------------------------
145 // desc: disallow deletion of locked objects
146 //-----------------------------------------------------------------------------
147 void Chuck_VM_Object::lock_all()
150 EM_log( CK_LOG_SYSTEM
, "locking down special objects..." );
152 our_locks_in_effect
= TRUE
;
158 //-----------------------------------------------------------------------------
159 // name: unlock_all()
160 // desc: allow deletion of locked objects (USE WITH CAUTION!)
161 //-----------------------------------------------------------------------------
162 void Chuck_VM_Object::unlock_all()
165 EM_log( CK_LOG_SYSTEM
, "unprotecting special objects..." );
167 our_locks_in_effect
= FALSE
;
174 Chuck_VM_Alloc
* Chuck_VM_Alloc::our_instance
= NULL
;
177 //-----------------------------------------------------------------------------
179 // desc: return static instance
180 //-----------------------------------------------------------------------------
181 Chuck_VM_Alloc
* Chuck_VM_Alloc::instance()
185 our_instance
= new Chuck_VM_Alloc
;
186 assert( our_instance
!= NULL
);
195 //-----------------------------------------------------------------------------
196 // name: add_object()
197 // desc: add newly allocated vm object
198 //-----------------------------------------------------------------------------
199 void Chuck_VM_Alloc::add_object( Chuck_VM_Object
* obj
)
202 if( DO_LOG( CK_LOG_CRAZY
) )
205 EM_log( CK_LOG_CRAZY
, "adding '%s' (0x%lx)...",
206 mini_type( typeid(*obj
).name() ), obj
);
215 //-----------------------------------------------------------------------------
216 // name: free_object()
217 // desc: free vm object - reference count should be 0
218 //-----------------------------------------------------------------------------
219 void Chuck_VM_Alloc::free_object( Chuck_VM_Object
* obj
)
221 // make sure the ref count is 0
222 assert( obj
&& obj
->m_ref_count
== 0 );
225 if( DO_LOG( CK_LOG_FINEST
) )
228 EM_log( CK_LOG_FINEST
, "freeing '%s' (0x%lx)...",
229 mini_type( typeid(*obj
).name() ), obj
);
232 // remove it from map
241 //-----------------------------------------------------------------------------
242 // name: Chuck_VM_Alloc()
244 //-----------------------------------------------------------------------------
245 Chuck_VM_Alloc::Chuck_VM_Alloc()
251 //-----------------------------------------------------------------------------
252 // name: ~Chuck_VM_Alloc()
254 //-----------------------------------------------------------------------------
255 Chuck_VM_Alloc::~Chuck_VM_Alloc()
261 //-----------------------------------------------------------------------------
262 // name: Chuck_Object()
264 //-----------------------------------------------------------------------------
265 Chuck_Object::Chuck_Object()
267 // zero virtual table
276 // add to vm allocator
277 Chuck_VM_Alloc::instance()->add_object( this );
283 //-----------------------------------------------------------------------------
284 // name: Chuck_Object()
286 //-----------------------------------------------------------------------------
287 Chuck_Object::~Chuck_Object()
290 if( vtable
) { delete vtable
; vtable
= NULL
; }
291 if( type_ref
) { type_ref
->release(); type_ref
= NULL
; }
292 if( data
) { delete [] data
; size
= 0; data
= NULL
; }
298 //-----------------------------------------------------------------------------
299 // name: Chuck_Array4()
301 //-----------------------------------------------------------------------------
302 Chuck_Array4::Chuck_Array4( t_CKBOOL is_obj
, t_CKINT capacity
)
305 assert( capacity
>= 0 );
307 m_vector
.resize( capacity
);
308 // clear (as non-object, so no releases)
310 this->zero( 0, m_vector
.capacity() );
311 // is object (set after clear)
318 //-----------------------------------------------------------------------------
319 // name: ~Chuck_Array4()
321 //-----------------------------------------------------------------------------
322 Chuck_Array4::~Chuck_Array4()
330 //-----------------------------------------------------------------------------
333 //-----------------------------------------------------------------------------
334 t_CKUINT
Chuck_Array4::addr( t_CKINT i
)
337 if( i
< 0 || i
>= m_vector
.capacity() )
341 return (t_CKUINT
)(&m_vector
[i
]);
347 //-----------------------------------------------------------------------------
350 //-----------------------------------------------------------------------------
351 t_CKUINT
Chuck_Array4::addr( const string
& key
)
354 return (t_CKUINT
)(&m_map
[key
]);
360 //-----------------------------------------------------------------------------
363 //-----------------------------------------------------------------------------
364 t_CKINT
Chuck_Array4::get( t_CKINT i
, t_CKUINT
* val
)
367 if( i
< 0 || i
>= m_vector
.capacity() )
380 //-----------------------------------------------------------------------------
383 //-----------------------------------------------------------------------------
384 t_CKINT
Chuck_Array4::get( const string
& key
, t_CKUINT
* val
)
389 map
<string
, t_CKUINT
>::iterator iter
= m_map
.find( key
);
391 if( iter
!= m_map
.end() ) *val
= (*iter
).second
;
400 //-----------------------------------------------------------------------------
402 // desc: include ref counting
403 //-----------------------------------------------------------------------------
404 t_CKINT
Chuck_Array4::set( t_CKINT i
, t_CKUINT val
)
407 if( i
< 0 || i
>= m_vector
.capacity() )
410 t_CKUINT v
= m_vector
[i
];
413 if( m_is_obj
&& v
) ((Chuck_Object
*)v
)->release();
419 if( m_is_obj
&& val
) ((Chuck_Object
*)val
)->add_ref();
429 //-----------------------------------------------------------------------------
431 // desc: include ref counting
432 //-----------------------------------------------------------------------------
433 t_CKINT
Chuck_Array4::set( const string
& key
, t_CKUINT val
)
435 map
<string
, t_CKUINT
>::iterator iter
= m_map
.find( key
);
438 if( m_is_obj
&& iter
!= m_map
.end() )
439 ((Chuck_Object
*)(*iter
).second
)->release();
441 if( !val
) m_map
.erase( key
);
442 else m_map
[key
] = val
;
445 if( m_is_obj
&& val
) ((Chuck_Object
*)val
)->add_ref();
454 //-----------------------------------------------------------------------------
457 //-----------------------------------------------------------------------------
458 t_CKINT
Chuck_Array4::find( const string
& key
)
460 return m_map
.find( key
) != m_map
.end();
466 //-----------------------------------------------------------------------------
469 //-----------------------------------------------------------------------------
470 t_CKINT
Chuck_Array4::erase( const string
& key
)
472 map
<string
, t_CKUINT
>::iterator iter
= m_map
.find( key
);
473 t_CKINT v
= iter
!= m_map
.end();
476 if( m_is_obj
&& iter
!= m_map
.end() )
477 ((Chuck_Object
*)(*iter
).second
)->release();
480 if( v
) m_map
.erase( key
);
488 //-----------------------------------------------------------------------------
491 //-----------------------------------------------------------------------------
492 t_CKINT
Chuck_Array4::push_back( t_CKUINT val
)
494 // TODO: release reference or assume 0?
497 m_vector
.push_back( val
);
505 //-----------------------------------------------------------------------------
508 //-----------------------------------------------------------------------------
509 t_CKINT
Chuck_Array4::pop_back( )
512 if( m_vector
.size() == 0 )
518 Chuck_Object
* v
= (Chuck_Object
*)m_vector
[m_vector
.size()-1];
519 if( v
) v
->release();
523 m_vector
[m_vector
.size()-1] = 0;
533 //-----------------------------------------------------------------------------
536 //-----------------------------------------------------------------------------
537 t_CKINT
Chuck_Array4::back( t_CKUINT
* val
) const
540 if( m_vector
.size() == 0 )
544 *val
= m_vector
.back();
552 //-----------------------------------------------------------------------------
555 //-----------------------------------------------------------------------------
556 void Chuck_Array4::clear( )
559 zero( 0, m_vector
.size() );
568 //-----------------------------------------------------------------------------
569 // name: set_capacity()
571 //-----------------------------------------------------------------------------
572 t_CKINT
Chuck_Array4::set_capacity( t_CKINT capacity
)
575 assert( capacity
>= 0 );
578 set_size( capacity
);
580 return m_vector
.capacity();
586 //-----------------------------------------------------------------------------
589 //-----------------------------------------------------------------------------
590 t_CKINT
Chuck_Array4::set_size( t_CKINT size
)
596 if( size
< m_vector
.size() )
599 zero( size
, m_vector
.size() );
603 t_CKINT size2
= m_vector
.size();
605 m_vector
.resize( size
);
608 if( m_vector
.size() > size2
)
611 zero( size2
, m_vector
.size() );
614 return m_vector
.size();
620 //-----------------------------------------------------------------------------
623 //-----------------------------------------------------------------------------
624 void Chuck_Array4::zero( t_CKUINT start
, t_CKUINT end
)
627 assert( start
<= m_vector
.capacity() && end
<= m_vector
.capacity() );
629 // if contains objects
632 Chuck_Object
* v
= NULL
;
633 for( t_CKUINT i
= start
; i
< end
; i
++ )
636 v
= (Chuck_Object
*)m_vector
[i
];
647 for( t_CKUINT i
= start
; i
< end
; i
++ )
658 //-----------------------------------------------------------------------------
659 // name: Chuck_Array8()
661 //-----------------------------------------------------------------------------
662 Chuck_Array8::Chuck_Array8( t_CKINT capacity
)
665 assert( capacity
>= 0 );
667 m_vector
.resize( capacity
);
669 this->zero( 0, m_vector
.capacity() );
675 //-----------------------------------------------------------------------------
676 // name: ~Chuck_Array8()
678 //-----------------------------------------------------------------------------
679 Chuck_Array8::~Chuck_Array8()
687 //-----------------------------------------------------------------------------
690 //-----------------------------------------------------------------------------
691 t_CKUINT
Chuck_Array8::addr( t_CKINT i
)
694 if( i
< 0 || i
>= m_vector
.capacity() )
698 return (t_CKUINT
)(&m_vector
[i
]);
704 //-----------------------------------------------------------------------------
707 //-----------------------------------------------------------------------------
708 t_CKUINT
Chuck_Array8::addr( const string
& key
)
711 return (t_CKUINT
)(&m_map
[key
]);
717 //-----------------------------------------------------------------------------
720 //-----------------------------------------------------------------------------
721 t_CKINT
Chuck_Array8::get( t_CKINT i
, t_CKFLOAT
* val
)
724 if( i
< 0 || i
>= m_vector
.capacity() )
737 //-----------------------------------------------------------------------------
740 //-----------------------------------------------------------------------------
741 t_CKINT
Chuck_Array8::get( const string
& key
, t_CKFLOAT
* val
)
747 map
<string
, t_CKFLOAT
>::iterator iter
= m_map
.find( key
);
750 if( iter
!= m_map
.end() )
753 *val
= (*iter
).second
;
763 //-----------------------------------------------------------------------------
766 //-----------------------------------------------------------------------------
767 t_CKINT
Chuck_Array8::set( t_CKINT i
, t_CKFLOAT val
)
770 if( i
< 0 || i
>= m_vector
.capacity() )
783 //-----------------------------------------------------------------------------
786 //-----------------------------------------------------------------------------
787 t_CKINT
Chuck_Array8::set( const string
& key
, t_CKFLOAT val
)
789 map
<string
, t_CKFLOAT
>::iterator iter
= m_map
.find( key
);
791 if( !val
) m_map
.erase( key
);
792 else m_map
[key
] = val
;
801 //-----------------------------------------------------------------------------
804 //-----------------------------------------------------------------------------
805 t_CKINT
Chuck_Array8::find( const string
& key
)
807 return m_map
.find( key
) != m_map
.end();
812 //-----------------------------------------------------------------------------
815 //-----------------------------------------------------------------------------
816 t_CKINT
Chuck_Array8::erase( const string
& key
)
818 return m_map
.erase( key
);
824 //-----------------------------------------------------------------------------
827 //-----------------------------------------------------------------------------
828 t_CKINT
Chuck_Array8::push_back( t_CKFLOAT val
)
831 m_vector
.push_back( val
);
839 //-----------------------------------------------------------------------------
842 //-----------------------------------------------------------------------------
843 t_CKINT
Chuck_Array8::pop_back( )
846 if( m_vector
.size() == 0 )
850 m_vector
[m_vector
.size()-1] = 0.0;
860 //-----------------------------------------------------------------------------
863 //-----------------------------------------------------------------------------
864 t_CKINT
Chuck_Array8::back( t_CKFLOAT
* val
) const
867 if( m_vector
.size() == 0 )
871 *val
= m_vector
.back();
879 //-----------------------------------------------------------------------------
882 //-----------------------------------------------------------------------------
883 void Chuck_Array8::clear( )
886 zero( 0, m_vector
.size() );
895 //-----------------------------------------------------------------------------
896 // name: set_capacity()
898 //-----------------------------------------------------------------------------
899 t_CKINT
Chuck_Array8::set_capacity( t_CKINT capacity
)
902 assert( capacity
>= 0 );
905 set_size( capacity
);
907 return m_vector
.capacity();
913 //-----------------------------------------------------------------------------
916 //-----------------------------------------------------------------------------
917 t_CKINT
Chuck_Array8::set_size( t_CKINT size
)
923 if( size
< m_vector
.size() )
926 zero( size
, m_vector
.size() );
930 t_CKINT size2
= m_vector
.size();
932 m_vector
.resize( size
);
935 if( m_vector
.size() > size2
)
938 zero( size2
, m_vector
.size() );
941 return m_vector
.size();
947 //-----------------------------------------------------------------------------
950 //-----------------------------------------------------------------------------
951 void Chuck_Array8::zero( t_CKUINT start
, t_CKUINT end
)
954 assert( start
<= m_vector
.capacity() && end
<= m_vector
.capacity() );
956 for( t_CKUINT i
= start
; i
< end
; i
++ )
966 //-----------------------------------------------------------------------------
967 // name: Chuck_Array16()
969 //-----------------------------------------------------------------------------
970 Chuck_Array16::Chuck_Array16( t_CKINT capacity
)
973 assert( capacity
>= 0 );
975 m_vector
.resize( capacity
);
977 this->zero( 0, m_vector
.capacity() );
983 //-----------------------------------------------------------------------------
984 // name: ~Chuck_Array16()
986 //-----------------------------------------------------------------------------
987 Chuck_Array16::~Chuck_Array16()
995 //-----------------------------------------------------------------------------
998 //-----------------------------------------------------------------------------
999 t_CKUINT
Chuck_Array16::addr( t_CKINT i
)
1002 if( i
< 0 || i
>= m_vector
.capacity() )
1006 return (t_CKUINT
)(&m_vector
[i
]);
1012 //-----------------------------------------------------------------------------
1015 //-----------------------------------------------------------------------------
1016 t_CKUINT
Chuck_Array16::addr( const string
& key
)
1019 return (t_CKUINT
)(&m_map
[key
]);
1025 //-----------------------------------------------------------------------------
1028 //-----------------------------------------------------------------------------
1029 t_CKINT
Chuck_Array16::get( t_CKINT i
, t_CKCOMPLEX
* val
)
1032 if( i
< 0 || i
>= m_vector
.capacity() )
1045 //-----------------------------------------------------------------------------
1048 //-----------------------------------------------------------------------------
1049 t_CKINT
Chuck_Array16::get( const string
& key
, t_CKCOMPLEX
* val
)
1056 map
<string
, t_CKCOMPLEX
>::iterator iter
= m_map
.find( key
);
1059 if( iter
!= m_map
.end() )
1062 *val
= (*iter
).second
;
1072 //-----------------------------------------------------------------------------
1075 //-----------------------------------------------------------------------------
1076 t_CKINT
Chuck_Array16::set( t_CKINT i
, t_CKCOMPLEX val
)
1079 if( i
< 0 || i
>= m_vector
.capacity() )
1092 //-----------------------------------------------------------------------------
1095 //-----------------------------------------------------------------------------
1096 t_CKINT
Chuck_Array16::set( const string
& key
, t_CKCOMPLEX val
)
1098 map
<string
, t_CKCOMPLEX
>::iterator iter
= m_map
.find( key
);
1100 if( val
.re
== 0 && val
.im
== 0 ) m_map
.erase( key
);
1101 else m_map
[key
] = val
;
1110 //-----------------------------------------------------------------------------
1113 //-----------------------------------------------------------------------------
1114 t_CKINT
Chuck_Array16::find( const string
& key
)
1116 return m_map
.find( key
) != m_map
.end();
1121 //-----------------------------------------------------------------------------
1124 //-----------------------------------------------------------------------------
1125 t_CKINT
Chuck_Array16::erase( const string
& key
)
1127 return m_map
.erase( key
);
1133 //-----------------------------------------------------------------------------
1134 // name: push_back()
1136 //-----------------------------------------------------------------------------
1137 t_CKINT
Chuck_Array16::push_back( t_CKCOMPLEX val
)
1140 m_vector
.push_back( val
);
1148 //-----------------------------------------------------------------------------
1151 //-----------------------------------------------------------------------------
1152 t_CKINT
Chuck_Array16::pop_back( )
1155 if( m_vector
.size() == 0 )
1159 m_vector
[m_vector
.size()-1].re
= 0.0;
1160 m_vector
[m_vector
.size()-1].im
= 0.0;
1162 m_vector
.pop_back();
1170 //-----------------------------------------------------------------------------
1173 //-----------------------------------------------------------------------------
1174 t_CKINT
Chuck_Array16::back( t_CKCOMPLEX
* val
) const
1177 if( m_vector
.size() == 0 )
1181 *val
= m_vector
.back();
1189 //-----------------------------------------------------------------------------
1192 //-----------------------------------------------------------------------------
1193 void Chuck_Array16::clear( )
1196 zero( 0, m_vector
.size() );
1199 // m_vector.clear();
1205 //-----------------------------------------------------------------------------
1206 // name: set_capacity()
1208 //-----------------------------------------------------------------------------
1209 t_CKINT
Chuck_Array16::set_capacity( t_CKINT capacity
)
1212 assert( capacity
>= 0 );
1215 set_size( capacity
);
1217 return m_vector
.capacity();
1223 //-----------------------------------------------------------------------------
1226 //-----------------------------------------------------------------------------
1227 t_CKINT
Chuck_Array16::set_size( t_CKINT size
)
1230 assert( size
>= 0 );
1233 if( size
< m_vector
.size() )
1236 zero( size
, m_vector
.size() );
1240 t_CKINT size2
= m_vector
.size();
1242 m_vector
.resize( size
);
1245 if( m_vector
.size() > size2
)
1248 zero( size2
, m_vector
.size() );
1251 return m_vector
.size();
1257 //-----------------------------------------------------------------------------
1260 //-----------------------------------------------------------------------------
1261 void Chuck_Array16::zero( t_CKUINT start
, t_CKUINT end
)
1264 assert( start
<= m_vector
.capacity() && end
<= m_vector
.capacity() );
1266 for( t_CKUINT i
= start
; i
< end
; i
++ )
1269 m_vector
[i
].re
= 0.0;
1270 m_vector
[i
].im
= 0.0;
1278 t_CKUINT
Chuck_Event::our_can_wait
= 0;
1280 //-----------------------------------------------------------------------------
1282 // desc: signal a event/condition variable, shreduling the next waiting shred
1283 // (if there is one or more)
1284 //-----------------------------------------------------------------------------
1285 void Chuck_Event::signal()
1287 m_queue_lock
.acquire();
1288 if( !m_queue
.empty() )
1290 Chuck_VM_Shred
* shred
= m_queue
.front();
1292 m_queue_lock
.release();
1293 Chuck_VM_Shreduler
* shreduler
= shred
->vm_ref
->shreduler();
1294 shred
->event
= NULL
;
1295 shreduler
->remove_blocked( shred
);
1296 shreduler
->shredule( shred
);
1297 // push the current time
1298 t_CKTIME
*& sp
= (t_CKTIME
*&)shred
->reg
->sp
;
1299 push_( sp
, shreduler
->now_system
);
1302 m_queue_lock
.release();
1308 //-----------------------------------------------------------------------------
1310 // desc: remove a shred from the event queue.
1311 //-----------------------------------------------------------------------------
1312 t_CKBOOL
Chuck_Event::remove( Chuck_VM_Shred
* shred
)
1314 queue
<Chuck_VM_Shred
*> temp
;
1315 t_CKBOOL removed
= FALSE
;
1316 m_queue_lock
.acquire();
1317 while( !m_queue
.empty() )
1319 if( m_queue
.front() != shred
)
1320 temp
.push( m_queue
.front() );
1322 shred
->event
= NULL
;
1329 m_queue_lock
.release();
1336 //-----------------------------------------------------------------------------
1337 // name: queue_broadcast()
1338 // desc: queue the event to broadcast a event/condition variable, by the owner
1340 //-----------------------------------------------------------------------------
1341 void Chuck_Event::queue_broadcast()
1343 // TODO: handle multiple VM
1344 m_queue_lock
.acquire();
1345 if( !m_queue
.empty() )
1347 Chuck_VM_Shred
* shred
= m_queue
.front();
1348 m_queue_lock
.release();
1349 shred
->vm_ref
->queue_event( this, 1 );
1352 m_queue_lock
.release();
1359 //-----------------------------------------------------------------------------
1360 // name: broadcast()
1361 // desc: broadcast a event/condition variable, shreduling all waiting shreds
1362 //-----------------------------------------------------------------------------
1363 void Chuck_Event::broadcast()
1365 m_queue_lock
.acquire();
1366 while( !m_queue
.empty() )
1368 m_queue_lock
.release();
1370 m_queue_lock
.acquire();
1372 m_queue_lock
.release();
1378 //-----------------------------------------------------------------------------
1380 // desc: cause event/condition variable to block the current shred, putting it
1381 // on its waiting list, and suspennd the shred from the VM.
1382 //-----------------------------------------------------------------------------
1383 void Chuck_Event::wait( Chuck_VM_Shred
* shred
, Chuck_VM
* vm
)
1385 EM_log( CK_LOG_FINE
, "shred '%d' wait on event '%x'...", shred
->xid
, (t_CKUINT
)this );
1386 // make sure the shred info matches the vm
1387 assert( shred
->vm_ref
== vm
);
1389 Chuck_DL_Return RETURN
;
1390 f_mfun canwaitplease
= (f_mfun
)this->vtable
->funcs
[our_can_wait
]->code
->native_func
;
1391 canwaitplease( this, NULL
, &RETURN
, shred
); // TODO: check this is right shred
1392 // RETURN.v_int = 1;
1394 // see if we can wait
1398 shred
->is_running
= FALSE
;
1400 // add to waiting list
1401 m_queue_lock
.acquire();
1402 m_queue
.push( shred
);
1403 m_queue_lock
.release();
1405 // add event to shred
1406 assert( shred
->event
== NULL
);
1407 shred
->event
= this;
1409 // add shred to shreduler
1410 vm
->shreduler()->add_blocked( shred
);
1414 // push the current time
1415 t_CKTIME
*& sp
= (t_CKTIME
*&)shred
->reg
->sp
;
1416 push_( sp
, shred
->now
);
1423 //-----------------------------------------------------------------------------
1426 //-----------------------------------------------------------------------------
1427 Chuck_IO::Chuck_IO()
1433 //-----------------------------------------------------------------------------
1436 //-----------------------------------------------------------------------------
1437 Chuck_IO::~Chuck_IO()
1443 //-----------------------------------------------------------------------------
1446 //-----------------------------------------------------------------------------
1447 Chuck_IO_File
* Chuck_IO::openFile( const string
& path
, t_CKINT flags
)
1455 //-----------------------------------------------------------------------------
1458 //-----------------------------------------------------------------------------
1459 string
Chuck_IO::currentDir()
1467 //-----------------------------------------------------------------------------
1470 //-----------------------------------------------------------------------------
1471 string
Chuck_IO::changeDir( const string
& to
)
1479 //-----------------------------------------------------------------------------
1482 //-----------------------------------------------------------------------------
1483 t_CKBOOL
Chuck_IO::isFile( const string
& path
)
1491 //-----------------------------------------------------------------------------
1494 //-----------------------------------------------------------------------------
1495 t_CKBOOL
Chuck_IO::isDir( const string
& path
)
1503 //-----------------------------------------------------------------------------
1506 //-----------------------------------------------------------------------------
1507 t_CKINT
Chuck_IO::getSize( const string
& path
)
1515 //-----------------------------------------------------------------------------
1518 //-----------------------------------------------------------------------------
1519 string
Chuck_IO::baseName( const string
& path
)
1527 //-----------------------------------------------------------------------------
1530 //-----------------------------------------------------------------------------
1531 void Chuck_IO::getContent( vector
<string
> & content
)
1539 //-----------------------------------------------------------------------------
1540 // name: Chuck_IO_File()
1541 // desc: constructor
1542 //-----------------------------------------------------------------------------
1543 Chuck_IO_File::Chuck_IO_File()
1553 //-----------------------------------------------------------------------------
1554 // name: ~Chuck_IO_File()
1556 //-----------------------------------------------------------------------------
1557 Chuck_IO_File::~Chuck_IO_File()
1566 //-----------------------------------------------------------------------------
1568 // desc: open file from disk
1569 //-----------------------------------------------------------------------------
1570 t_CKBOOL
Chuck_IO_File::open( const string
& path
, t_CKINT flags
)
1576 EM_log( CK_LOG_INFO
, "(IO): opening file from disk..." );
1578 EM_log( CK_LOG_INFO
, "(IO): path: %s", path
.c_str() );
1579 EM_log( CK_LOG_INFO
, "(IO): READ: %s WRITE: %s APPEND: %s PLUS: %s",
1580 flags
& Chuck_IO::READ
? "Y" : "N", flags
& Chuck_IO::WRITE
? "Y" : "N",
1581 flags
& Chuck_IO::APPEND
? "Y" : "N", flags
& Chuck_IO::TRUNCATE
? "Y" : "N",
1582 flags
& Chuck_IO::BINARY
? "Y" : "N" );
1587 // construct mode string
1589 if( flags
& Chuck_IO::READ
)
1594 m_ready_flags
|= Chuck_IO::READ
;
1598 if( flags
& Chuck_IO::WRITE
)
1603 m_ready_flags
|= Chuck_IO::WRITE
;
1607 if( flags
& Chuck_IO::APPEND
)
1612 m_ready_flags
|= Chuck_IO::WRITE
| Chuck_IO::APPEND
;
1614 nMode
|= ios::out
| ios::ate
;
1616 if( flags
& Chuck_IO::TRUNCATE
)
1619 if( flags
^ Chuck_IO::WRITE
|| flags
& Chuck_IO::APPEND
)
1622 EM_error3( "(FileIO): malformed open flag (TRUNCATE)..." );
1623 EM_error3( " note: must be used with WRITE, and without APPEND" );
1630 m_ready_flags
|= Chuck_IO::TRUNCATE
;
1632 nMode
|= ios::trunc
;
1634 if( flags
& Chuck_IO::BINARY
)
1637 m_ready_flags
|= Chuck_IO::BINARY
;
1641 if( sout
.str().length() == 0 )
1644 EM_error3( "(FileIO): malformed open flag (no operation specified)..." );
1649 EM_log( CK_LOG_INFO
, "(IO): flag: '%s'", sout
.str().c_str() );
1651 // windows sucks for being creative in the wrong places
1652 #ifdef __PLATFORM_WIN32__
1653 // if( flags ^ Chuck_IO::TRUNCATE && flags | Chuck_IO::READ ) nMode |= ios::nocreate;
1654 m_io
.open( path
.c_str(), nMode
);
1656 m_io
.open( path
.c_str(), (_Ios_Openmode
)nMode
);
1662 EM_error3( "(FileIO): cannot open file: '%s'", path
.c_str() );
1699 //-----------------------------------------------------------------------------
1702 //-----------------------------------------------------------------------------
1703 t_CKBOOL
Chuck_IO_File::close()
1710 EM_log( CK_LOG_INFO
, "(IO): closing file '%s'...", m_path
.c_str() );
1723 //-----------------------------------------------------------------------------
1725 // desc: is there more to read?
1726 //-----------------------------------------------------------------------------
1727 t_CKBOOL
Chuck_IO_File::more()
1735 //-----------------------------------------------------------------------------
1737 // desc: end of file?
1738 //-----------------------------------------------------------------------------
1739 t_CKBOOL
Chuck_IO_File::eof()
1742 if( !m_io
.good() ) return TRUE
;
1749 //-----------------------------------------------------------------------------
1750 // name: good2read()
1751 // desc: ready to read?
1752 //-----------------------------------------------------------------------------
1753 t_CKBOOL
Chuck_IO_File::good2read()
1755 return ( m_io
.good() && m_flags
& Chuck_IO::READ
);
1761 //-----------------------------------------------------------------------------
1762 // name: good2write()
1763 // desc: ready for write?
1764 //-----------------------------------------------------------------------------
1765 t_CKBOOL
Chuck_IO_File::good2write()
1767 return ( m_io
.good() && m_flags
& Chuck_IO::READ
);
1773 //-----------------------------------------------------------------------------
1775 // desc: read next as (ascii) integer
1776 //-----------------------------------------------------------------------------
1777 t_CKINT
Chuck_IO_File::readInt()
1780 if( !good2read() ) return 0;
1784 // TODO: check for EOF?
1793 //-----------------------------------------------------------------------------
1794 // name: readFloat()
1795 // desc: read next as (ascii) floating point value
1796 //-----------------------------------------------------------------------------
1797 t_CKFLOAT
Chuck_IO_File::readFloat()
1800 if( !good2read() ) return 0;
1804 // TODO: check for EOF?
1813 //-----------------------------------------------------------------------------
1814 // name: readString()
1815 // desc: read next as string
1816 //-----------------------------------------------------------------------------
1817 string
Chuck_IO_File::readString()
1820 if( !good2read() ) return 0;
1824 // TODO: check for EOF?
1833 //-----------------------------------------------------------------------------
1836 //-----------------------------------------------------------------------------
1837 string
Chuck_IO_File::readLine()
1840 if( !good2read() ) return 0;
1844 // TODO: check for EOF?
1845 std::getline( m_io
, val
);
1853 //-----------------------------------------------------------------------------
1855 // desc: write (ascii) integer
1856 //-----------------------------------------------------------------------------
1857 t_CKBOOL
Chuck_IO_File::writeInt( t_CKINT val
)
1860 if( !good2write() ) return FALSE
;
1871 //-----------------------------------------------------------------------------
1872 // name: writeFloat()
1873 // desc: write (ascii) floating point value
1874 //-----------------------------------------------------------------------------
1875 t_CKBOOL
Chuck_IO_File::writeFloat( t_CKFLOAT val
)
1878 if( !good2write() ) return 0;
1889 //-----------------------------------------------------------------------------
1890 // name: writeString()
1891 // desc: write string
1892 //-----------------------------------------------------------------------------
1893 t_CKBOOL
Chuck_IO_File::writeString( const string
& val
)
1896 if( !good2read() ) return 0;
1907 //-----------------------------------------------------------------------------
1908 // name: writeLine()
1910 //-----------------------------------------------------------------------------
1911 t_CKBOOL
Chuck_IO_File::writeLine( const string
& val
)
1914 if( !good2read() ) return 0;
1917 m_io
<< val
<< endl
;
1926 //-----------------------------------------------------------------------------
1928 // desc: read next 32 bits, return as int
1929 //-----------------------------------------------------------------------------
1930 t_CKINT
Chuck_IO_File::read32i()
1938 //-----------------------------------------------------------------------------
1940 // desc: read next 24 bits, return as int
1941 //-----------------------------------------------------------------------------
1942 t_CKINT
Chuck_IO_File::read24i()
1950 //-----------------------------------------------------------------------------
1952 // desc: read next 16 bits, return as int
1953 //-----------------------------------------------------------------------------
1954 t_CKINT
Chuck_IO_File::read16i()
1962 //-----------------------------------------------------------------------------
1964 // desc: return next 8 bits, return as int
1965 //-----------------------------------------------------------------------------
1966 t_CKINT
Chuck_IO_File::read8i()
1974 //-----------------------------------------------------------------------------
1976 // desc: return next 32-bits as (binary) single float
1977 //-----------------------------------------------------------------------------
1978 t_CKSINGLE
Chuck_IO_File::read32f()
1986 //-----------------------------------------------------------------------------
1988 // desc: return next 64-bits as (binary) double float
1989 //-----------------------------------------------------------------------------
1990 t_CKDOUBLE
Chuck_IO_File::read64f()