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
.reserve( capacity
);
309 m_vector
.resize( capacity
);
310 // clear (as non-object, so no releases)
312 this->zero( 0, m_vector
.capacity() );
313 // is object (set after clear)
320 //-----------------------------------------------------------------------------
321 // name: ~Chuck_Array4()
323 //-----------------------------------------------------------------------------
324 Chuck_Array4::~Chuck_Array4()
332 //-----------------------------------------------------------------------------
335 //-----------------------------------------------------------------------------
336 t_CKUINT
Chuck_Array4::addr( t_CKINT i
)
339 if( i
< 0 || i
>= m_vector
.capacity() )
343 return (t_CKUINT
)(&m_vector
[i
]);
349 //-----------------------------------------------------------------------------
352 //-----------------------------------------------------------------------------
353 t_CKUINT
Chuck_Array4::addr( const string
& key
)
356 return (t_CKUINT
)(&m_map
[key
]);
362 //-----------------------------------------------------------------------------
365 //-----------------------------------------------------------------------------
366 t_CKINT
Chuck_Array4::get( t_CKINT i
, t_CKUINT
* val
)
369 if( i
< 0 || i
>= m_vector
.capacity() )
382 //-----------------------------------------------------------------------------
385 //-----------------------------------------------------------------------------
386 t_CKINT
Chuck_Array4::get( const string
& key
, t_CKUINT
* val
)
391 map
<string
, t_CKUINT
>::iterator iter
= m_map
.find( key
);
393 if( iter
!= m_map
.end() ) *val
= (*iter
).second
;
402 //-----------------------------------------------------------------------------
404 // desc: include ref counting
405 //-----------------------------------------------------------------------------
406 t_CKINT
Chuck_Array4::set( t_CKINT i
, t_CKUINT val
)
409 if( i
< 0 || i
>= m_vector
.capacity() )
412 t_CKUINT v
= m_vector
[i
];
415 if( m_is_obj
&& v
) ((Chuck_Object
*)v
)->release();
421 if( m_is_obj
&& val
) ((Chuck_Object
*)val
)->add_ref();
431 //-----------------------------------------------------------------------------
433 // desc: include ref counting
434 //-----------------------------------------------------------------------------
435 t_CKINT
Chuck_Array4::set( const string
& key
, t_CKUINT val
)
437 map
<string
, t_CKUINT
>::iterator iter
= m_map
.find( key
);
440 if( m_is_obj
&& iter
!= m_map
.end() )
441 ((Chuck_Object
*)(*iter
).second
)->release();
443 if( !val
) m_map
.erase( key
);
444 else m_map
[key
] = val
;
447 if( m_is_obj
&& val
) ((Chuck_Object
*)val
)->add_ref();
456 //-----------------------------------------------------------------------------
459 //-----------------------------------------------------------------------------
460 t_CKINT
Chuck_Array4::find( const string
& key
)
462 return m_map
.find( key
) != m_map
.end();
468 //-----------------------------------------------------------------------------
471 //-----------------------------------------------------------------------------
472 t_CKINT
Chuck_Array4::erase( const string
& key
)
474 map
<string
, t_CKUINT
>::iterator iter
= m_map
.find( key
);
475 t_CKINT v
= iter
!= m_map
.end();
478 if( m_is_obj
&& iter
!= m_map
.end() )
479 ((Chuck_Object
*)(*iter
).second
)->release();
482 if( v
) m_map
.erase( key
);
490 //-----------------------------------------------------------------------------
493 //-----------------------------------------------------------------------------
494 t_CKINT
Chuck_Array4::push_back( t_CKUINT val
)
496 // TODO: release reference or assume 0?
499 m_vector
.push_back( val
);
507 //-----------------------------------------------------------------------------
510 //-----------------------------------------------------------------------------
511 t_CKINT
Chuck_Array4::pop_back( )
514 if( m_vector
.size() == 0 )
520 Chuck_Object
* v
= (Chuck_Object
*)m_vector
[m_vector
.size()-1];
521 if( v
) v
->release();
525 m_vector
[m_vector
.size()-1] = 0;
535 //-----------------------------------------------------------------------------
538 //-----------------------------------------------------------------------------
539 t_CKINT
Chuck_Array4::back( t_CKUINT
* val
) const
542 if( m_vector
.size() == 0 )
546 *val
= m_vector
.back();
554 //-----------------------------------------------------------------------------
557 //-----------------------------------------------------------------------------
558 void Chuck_Array4::clear( )
561 zero( 0, m_vector
.size() );
570 //-----------------------------------------------------------------------------
571 // name: set_capacity()
573 //-----------------------------------------------------------------------------
574 t_CKINT
Chuck_Array4::set_capacity( t_CKINT capacity
)
577 assert( capacity
>= 0 );
579 // if clearing capacity
580 if( capacity
< m_vector
.size() )
583 set_size( capacity
);
587 m_vector
.reserve( capacity
);
589 return m_vector
.capacity();
595 //-----------------------------------------------------------------------------
598 //-----------------------------------------------------------------------------
599 t_CKINT
Chuck_Array4::set_size( t_CKINT size
)
605 if( size
< m_vector
.size() )
608 zero( size
, m_vector
.size() );
612 m_vector
.resize( 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
.reserve( capacity
);
669 m_vector
.resize( capacity
);
671 this->zero( 0, m_vector
.capacity() );
677 //-----------------------------------------------------------------------------
678 // name: ~Chuck_Array8()
680 //-----------------------------------------------------------------------------
681 Chuck_Array8::~Chuck_Array8()
689 //-----------------------------------------------------------------------------
692 //-----------------------------------------------------------------------------
693 t_CKUINT
Chuck_Array8::addr( t_CKINT i
)
696 if( i
< 0 || i
>= m_vector
.capacity() )
700 return (t_CKUINT
)(&m_vector
[i
]);
706 //-----------------------------------------------------------------------------
709 //-----------------------------------------------------------------------------
710 t_CKUINT
Chuck_Array8::addr( const string
& key
)
713 return (t_CKUINT
)(&m_map
[key
]);
719 //-----------------------------------------------------------------------------
722 //-----------------------------------------------------------------------------
723 t_CKINT
Chuck_Array8::get( t_CKINT i
, t_CKFLOAT
* val
)
726 if( i
< 0 || i
>= m_vector
.capacity() )
739 //-----------------------------------------------------------------------------
742 //-----------------------------------------------------------------------------
743 t_CKINT
Chuck_Array8::get( const string
& key
, t_CKFLOAT
* val
)
749 map
<string
, t_CKFLOAT
>::iterator iter
= m_map
.find( key
);
752 if( iter
!= m_map
.end() )
755 *val
= (*iter
).second
;
765 //-----------------------------------------------------------------------------
768 //-----------------------------------------------------------------------------
769 t_CKINT
Chuck_Array8::set( t_CKINT i
, t_CKFLOAT val
)
772 if( i
< 0 || i
>= m_vector
.capacity() )
785 //-----------------------------------------------------------------------------
788 //-----------------------------------------------------------------------------
789 t_CKINT
Chuck_Array8::set( const string
& key
, t_CKFLOAT val
)
791 map
<string
, t_CKFLOAT
>::iterator iter
= m_map
.find( key
);
793 if( !val
) m_map
.erase( key
);
794 else m_map
[key
] = val
;
803 //-----------------------------------------------------------------------------
806 //-----------------------------------------------------------------------------
807 t_CKINT
Chuck_Array8::find( const string
& key
)
809 return m_map
.find( key
) != m_map
.end();
814 //-----------------------------------------------------------------------------
817 //-----------------------------------------------------------------------------
818 t_CKINT
Chuck_Array8::erase( const string
& key
)
820 return m_map
.erase( key
);
826 //-----------------------------------------------------------------------------
829 //-----------------------------------------------------------------------------
830 t_CKINT
Chuck_Array8::push_back( t_CKFLOAT val
)
833 m_vector
.push_back( val
);
841 //-----------------------------------------------------------------------------
844 //-----------------------------------------------------------------------------
845 t_CKINT
Chuck_Array8::pop_back( )
848 if( m_vector
.size() == 0 )
852 m_vector
[m_vector
.size()-1] = 0.0;
862 //-----------------------------------------------------------------------------
865 //-----------------------------------------------------------------------------
866 t_CKINT
Chuck_Array8::back( t_CKFLOAT
* val
) const
869 if( m_vector
.size() == 0 )
873 *val
= m_vector
.back();
881 //-----------------------------------------------------------------------------
884 //-----------------------------------------------------------------------------
885 void Chuck_Array8::clear( )
888 zero( 0, m_vector
.size() );
897 //-----------------------------------------------------------------------------
898 // name: set_capacity()
900 //-----------------------------------------------------------------------------
901 t_CKINT
Chuck_Array8::set_capacity( t_CKINT capacity
)
904 assert( capacity
>= 0 );
907 if( capacity
< m_vector
.size() )
908 set_size( capacity
);
911 m_vector
.reserve( capacity
);
913 return m_vector
.capacity();
919 //-----------------------------------------------------------------------------
922 //-----------------------------------------------------------------------------
923 t_CKINT
Chuck_Array8::set_size( t_CKINT size
)
929 if( size
< m_vector
.size() )
932 zero( size
, m_vector
.size() );
936 m_vector
.resize( size
);
938 return m_vector
.size();
944 //-----------------------------------------------------------------------------
947 //-----------------------------------------------------------------------------
948 void Chuck_Array8::zero( t_CKUINT start
, t_CKUINT end
)
951 assert( start
<= m_vector
.capacity() && end
<= m_vector
.capacity() );
953 for( t_CKUINT i
= start
; i
< end
; i
++ )
963 //-----------------------------------------------------------------------------
964 // name: Chuck_Array16()
966 //-----------------------------------------------------------------------------
967 Chuck_Array16::Chuck_Array16( t_CKINT capacity
)
970 assert( capacity
>= 0 );
972 m_vector
.reserve( capacity
);
974 m_vector
.resize( capacity
);
976 this->zero( 0, m_vector
.capacity() );
982 //-----------------------------------------------------------------------------
983 // name: ~Chuck_Array16()
985 //-----------------------------------------------------------------------------
986 Chuck_Array16::~Chuck_Array16()
994 //-----------------------------------------------------------------------------
997 //-----------------------------------------------------------------------------
998 t_CKUINT
Chuck_Array16::addr( t_CKINT i
)
1001 if( i
< 0 || i
>= m_vector
.capacity() )
1005 return (t_CKUINT
)(&m_vector
[i
]);
1011 //-----------------------------------------------------------------------------
1014 //-----------------------------------------------------------------------------
1015 t_CKUINT
Chuck_Array16::addr( const string
& key
)
1018 return (t_CKUINT
)(&m_map
[key
]);
1024 //-----------------------------------------------------------------------------
1027 //-----------------------------------------------------------------------------
1028 t_CKINT
Chuck_Array16::get( t_CKINT i
, t_CKCOMPLEX
* val
)
1031 if( i
< 0 || i
>= m_vector
.capacity() )
1044 //-----------------------------------------------------------------------------
1047 //-----------------------------------------------------------------------------
1048 t_CKINT
Chuck_Array16::get( const string
& key
, t_CKCOMPLEX
* val
)
1055 map
<string
, t_CKCOMPLEX
>::iterator iter
= m_map
.find( key
);
1058 if( iter
!= m_map
.end() )
1061 *val
= (*iter
).second
;
1071 //-----------------------------------------------------------------------------
1074 //-----------------------------------------------------------------------------
1075 t_CKINT
Chuck_Array16::set( t_CKINT i
, t_CKCOMPLEX val
)
1078 if( i
< 0 || i
>= m_vector
.capacity() )
1091 //-----------------------------------------------------------------------------
1094 //-----------------------------------------------------------------------------
1095 t_CKINT
Chuck_Array16::set( const string
& key
, t_CKCOMPLEX val
)
1097 map
<string
, t_CKCOMPLEX
>::iterator iter
= m_map
.find( key
);
1099 if( val
.re
== 0 && val
.im
== 0 ) m_map
.erase( key
);
1100 else m_map
[key
] = val
;
1109 //-----------------------------------------------------------------------------
1112 //-----------------------------------------------------------------------------
1113 t_CKINT
Chuck_Array16::find( const string
& key
)
1115 return m_map
.find( key
) != m_map
.end();
1120 //-----------------------------------------------------------------------------
1123 //-----------------------------------------------------------------------------
1124 t_CKINT
Chuck_Array16::erase( const string
& key
)
1126 return m_map
.erase( key
);
1132 //-----------------------------------------------------------------------------
1133 // name: push_back()
1135 //-----------------------------------------------------------------------------
1136 t_CKINT
Chuck_Array16::push_back( t_CKCOMPLEX val
)
1139 m_vector
.push_back( val
);
1147 //-----------------------------------------------------------------------------
1150 //-----------------------------------------------------------------------------
1151 t_CKINT
Chuck_Array16::pop_back( )
1154 if( m_vector
.size() == 0 )
1158 m_vector
[m_vector
.size()-1].re
= 0.0;
1159 m_vector
[m_vector
.size()-1].im
= 0.0;
1161 m_vector
.pop_back();
1169 //-----------------------------------------------------------------------------
1172 //-----------------------------------------------------------------------------
1173 t_CKINT
Chuck_Array16::back( t_CKCOMPLEX
* val
) const
1176 if( m_vector
.size() == 0 )
1180 *val
= m_vector
.back();
1188 //-----------------------------------------------------------------------------
1191 //-----------------------------------------------------------------------------
1192 void Chuck_Array16::clear( )
1195 zero( 0, m_vector
.size() );
1204 //-----------------------------------------------------------------------------
1205 // name: set_capacity()
1207 //-----------------------------------------------------------------------------
1208 t_CKINT
Chuck_Array16::set_capacity( t_CKINT capacity
)
1211 assert( capacity
>= 0 );
1214 if( capacity
< m_vector
.size() )
1215 set_size( capacity
);
1218 m_vector
.reserve( capacity
);
1220 return m_vector
.capacity();
1226 //-----------------------------------------------------------------------------
1229 //-----------------------------------------------------------------------------
1230 t_CKINT
Chuck_Array16::set_size( t_CKINT size
)
1233 assert( size
>= 0 );
1236 if( size
< m_vector
.size() )
1239 zero( size
, m_vector
.size() );
1243 m_vector
.resize( size
);
1245 return m_vector
.size();
1251 //-----------------------------------------------------------------------------
1254 //-----------------------------------------------------------------------------
1255 void Chuck_Array16::zero( t_CKUINT start
, t_CKUINT end
)
1258 assert( start
<= m_vector
.capacity() && end
<= m_vector
.capacity() );
1260 for( t_CKUINT i
= start
; i
< end
; i
++ )
1263 m_vector
[i
].re
= 0.0;
1264 m_vector
[i
].im
= 0.0;
1272 t_CKUINT
Chuck_Event::our_can_wait
= 0;
1274 //-----------------------------------------------------------------------------
1276 // desc: signal a event/condition variable, shreduling the next waiting shred
1277 // (if there is one or more)
1278 //-----------------------------------------------------------------------------
1279 void Chuck_Event::signal()
1281 m_queue_lock
.acquire();
1282 if( !m_queue
.empty() )
1284 Chuck_VM_Shred
* shred
= m_queue
.front();
1286 m_queue_lock
.release();
1287 Chuck_VM_Shreduler
* shreduler
= shred
->vm_ref
->shreduler();
1288 shred
->event
= NULL
;
1289 shreduler
->remove_blocked( shred
);
1290 shreduler
->shredule( shred
);
1291 // push the current time
1292 t_CKTIME
*& sp
= (t_CKTIME
*&)shred
->reg
->sp
;
1293 push_( sp
, shreduler
->now_system
);
1296 m_queue_lock
.release();
1302 //-----------------------------------------------------------------------------
1304 // desc: remove a shred from the event queue.
1305 //-----------------------------------------------------------------------------
1306 t_CKBOOL
Chuck_Event::remove( Chuck_VM_Shred
* shred
)
1308 queue
<Chuck_VM_Shred
*> temp
;
1309 t_CKBOOL removed
= FALSE
;
1310 m_queue_lock
.acquire();
1311 while( !m_queue
.empty() )
1313 if( m_queue
.front() != shred
)
1314 temp
.push( m_queue
.front() );
1316 shred
->event
= NULL
;
1323 m_queue_lock
.release();
1330 //-----------------------------------------------------------------------------
1331 // name: queue_broadcast()
1332 // desc: queue the event to broadcast a event/condition variable, by the owner
1334 //-----------------------------------------------------------------------------
1335 void Chuck_Event::queue_broadcast()
1337 // TODO: handle multiple VM
1338 m_queue_lock
.acquire();
1339 if( !m_queue
.empty() )
1341 Chuck_VM_Shred
* shred
= m_queue
.front();
1342 m_queue_lock
.release();
1343 shred
->vm_ref
->queue_event( this, 1 );
1346 m_queue_lock
.release();
1353 //-----------------------------------------------------------------------------
1354 // name: broadcast()
1355 // desc: broadcast a event/condition variable, shreduling all waiting shreds
1356 //-----------------------------------------------------------------------------
1357 void Chuck_Event::broadcast()
1359 m_queue_lock
.acquire();
1360 while( !m_queue
.empty() )
1362 m_queue_lock
.release();
1364 m_queue_lock
.acquire();
1366 m_queue_lock
.release();
1372 //-----------------------------------------------------------------------------
1374 // desc: cause event/condition variable to block the current shred, putting it
1375 // on its waiting list, and suspennd the shred from the VM.
1376 //-----------------------------------------------------------------------------
1377 void Chuck_Event::wait( Chuck_VM_Shred
* shred
, Chuck_VM
* vm
)
1379 EM_log( CK_LOG_FINE
, "shred '%d' wait on event '%x'...", shred
->xid
, (t_CKUINT
)this );
1380 // make sure the shred info matches the vm
1381 assert( shred
->vm_ref
== vm
);
1383 Chuck_DL_Return RETURN
;
1384 f_mfun canwaitplease
= (f_mfun
)this->vtable
->funcs
[our_can_wait
]->code
->native_func
;
1385 canwaitplease( this, NULL
, &RETURN
, shred
); // TODO: check this is right shred
1386 // RETURN.v_int = 1;
1388 // see if we can wait
1392 shred
->is_running
= FALSE
;
1394 // add to waiting list
1395 m_queue_lock
.acquire();
1396 m_queue
.push( shred
);
1397 m_queue_lock
.release();
1399 // add event to shred
1400 assert( shred
->event
== NULL
);
1401 shred
->event
= this;
1403 // add shred to shreduler
1404 vm
->shreduler()->add_blocked( shred
);
1408 // push the current time
1409 t_CKTIME
*& sp
= (t_CKTIME
*&)shred
->reg
->sp
;
1410 push_( sp
, shred
->now
);
1417 //-----------------------------------------------------------------------------
1420 //-----------------------------------------------------------------------------
1421 Chuck_IO::Chuck_IO()
1427 //-----------------------------------------------------------------------------
1430 //-----------------------------------------------------------------------------
1431 Chuck_IO::~Chuck_IO()
1437 //-----------------------------------------------------------------------------
1440 //-----------------------------------------------------------------------------
1441 Chuck_IO_File
* Chuck_IO::openFile( const string
& path
, t_CKINT flags
)
1449 //-----------------------------------------------------------------------------
1452 //-----------------------------------------------------------------------------
1453 string
Chuck_IO::currentDir()
1461 //-----------------------------------------------------------------------------
1464 //-----------------------------------------------------------------------------
1465 string
Chuck_IO::changeDir( const string
& to
)
1473 //-----------------------------------------------------------------------------
1476 //-----------------------------------------------------------------------------
1477 t_CKBOOL
Chuck_IO::isFile( const string
& path
)
1485 //-----------------------------------------------------------------------------
1488 //-----------------------------------------------------------------------------
1489 t_CKBOOL
Chuck_IO::isDir( const string
& path
)
1497 //-----------------------------------------------------------------------------
1500 //-----------------------------------------------------------------------------
1501 t_CKINT
Chuck_IO::getSize( const string
& path
)
1509 //-----------------------------------------------------------------------------
1512 //-----------------------------------------------------------------------------
1513 string
Chuck_IO::baseName( const string
& path
)
1521 //-----------------------------------------------------------------------------
1524 //-----------------------------------------------------------------------------
1525 void Chuck_IO::getContent( vector
<string
> & content
)
1533 //-----------------------------------------------------------------------------
1534 // name: Chuck_IO_File()
1535 // desc: constructor
1536 //-----------------------------------------------------------------------------
1537 Chuck_IO_File::Chuck_IO_File()
1547 //-----------------------------------------------------------------------------
1548 // name: ~Chuck_IO_File()
1550 //-----------------------------------------------------------------------------
1551 Chuck_IO_File::~Chuck_IO_File()
1560 //-----------------------------------------------------------------------------
1562 // desc: open file from disk
1563 //-----------------------------------------------------------------------------
1564 t_CKBOOL
Chuck_IO_File::open( const string
& path
, t_CKINT flags
)
1570 EM_log( CK_LOG_INFO
, "(IO): opening file from disk..." );
1572 EM_log( CK_LOG_INFO
, "(IO): path: %s", path
.c_str() );
1573 EM_log( CK_LOG_INFO
, "(IO): READ: %s WRITE: %s APPEND: %s PLUS: %s",
1574 flags
& Chuck_IO::READ
? "Y" : "N", flags
& Chuck_IO::WRITE
? "Y" : "N",
1575 flags
& Chuck_IO::APPEND
? "Y" : "N", flags
& Chuck_IO::TRUNCATE
? "Y" : "N",
1576 flags
& Chuck_IO::BINARY
? "Y" : "N" );
1581 // construct mode string
1583 if( flags
& Chuck_IO::READ
)
1588 m_ready_flags
|= Chuck_IO::READ
;
1592 if( flags
& Chuck_IO::WRITE
)
1597 m_ready_flags
|= Chuck_IO::WRITE
;
1601 if( flags
& Chuck_IO::APPEND
)
1606 m_ready_flags
|= Chuck_IO::WRITE
| Chuck_IO::APPEND
;
1608 nMode
|= ios::out
| ios::ate
;
1610 if( flags
& Chuck_IO::TRUNCATE
)
1613 if( flags
^ Chuck_IO::WRITE
|| flags
& Chuck_IO::APPEND
)
1616 EM_error3( "(FileIO): malformed open flag (TRUNCATE)..." );
1617 EM_error3( " note: must be used with WRITE, and without APPEND" );
1624 m_ready_flags
|= Chuck_IO::TRUNCATE
;
1626 nMode
|= ios::trunc
;
1628 if( flags
& Chuck_IO::BINARY
)
1631 m_ready_flags
|= Chuck_IO::BINARY
;
1635 if( sout
.str().length() == 0 )
1638 EM_error3( "(FileIO): malformed open flag (no operation specified)..." );
1643 EM_log( CK_LOG_INFO
, "(IO): flag: '%s'", sout
.str().c_str() );
1645 // windows sucks for being creative in the wrong places
1646 #ifdef __PLATFORM_WIN32__
1647 // if( flags ^ Chuck_IO::TRUNCATE && flags | Chuck_IO::READ ) nMode |= ios::nocreate;
1648 m_io
.open( path
.c_str(), nMode
);
1650 m_io
.open( path
.c_str(), (_Ios_Openmode
)nMode
);
1656 EM_error3( "(FileIO): cannot open file: '%s'", path
.c_str() );
1693 //-----------------------------------------------------------------------------
1696 //-----------------------------------------------------------------------------
1697 t_CKBOOL
Chuck_IO_File::close()
1704 EM_log( CK_LOG_INFO
, "(IO): closing file '%s'...", m_path
.c_str() );
1717 //-----------------------------------------------------------------------------
1719 // desc: is there more to read?
1720 //-----------------------------------------------------------------------------
1721 t_CKBOOL
Chuck_IO_File::more()
1729 //-----------------------------------------------------------------------------
1731 // desc: end of file?
1732 //-----------------------------------------------------------------------------
1733 t_CKBOOL
Chuck_IO_File::eof()
1736 if( !m_io
.good() ) return TRUE
;
1743 //-----------------------------------------------------------------------------
1744 // name: good2read()
1745 // desc: ready to read?
1746 //-----------------------------------------------------------------------------
1747 t_CKBOOL
Chuck_IO_File::good2read()
1749 return ( m_io
.good() && m_flags
& Chuck_IO::READ
);
1755 //-----------------------------------------------------------------------------
1756 // name: good2write()
1757 // desc: ready for write?
1758 //-----------------------------------------------------------------------------
1759 t_CKBOOL
Chuck_IO_File::good2write()
1761 return ( m_io
.good() && m_flags
& Chuck_IO::READ
);
1767 //-----------------------------------------------------------------------------
1769 // desc: read next as (ascii) integer
1770 //-----------------------------------------------------------------------------
1771 t_CKINT
Chuck_IO_File::readInt()
1774 if( !good2read() ) return 0;
1778 // TODO: check for EOF?
1787 //-----------------------------------------------------------------------------
1788 // name: readFloat()
1789 // desc: read next as (ascii) floating point value
1790 //-----------------------------------------------------------------------------
1791 t_CKFLOAT
Chuck_IO_File::readFloat()
1794 if( !good2read() ) return 0;
1798 // TODO: check for EOF?
1807 //-----------------------------------------------------------------------------
1808 // name: readString()
1809 // desc: read next as string
1810 //-----------------------------------------------------------------------------
1811 string
Chuck_IO_File::readString()
1814 if( !good2read() ) return 0;
1818 // TODO: check for EOF?
1827 //-----------------------------------------------------------------------------
1830 //-----------------------------------------------------------------------------
1831 string
Chuck_IO_File::readLine()
1834 if( !good2read() ) return 0;
1838 // TODO: check for EOF?
1839 std::getline( m_io
, val
);
1847 //-----------------------------------------------------------------------------
1849 // desc: write (ascii) integer
1850 //-----------------------------------------------------------------------------
1851 t_CKBOOL
Chuck_IO_File::writeInt( t_CKINT val
)
1854 if( !good2write() ) return FALSE
;
1865 //-----------------------------------------------------------------------------
1866 // name: writeFloat()
1867 // desc: write (ascii) floating point value
1868 //-----------------------------------------------------------------------------
1869 t_CKBOOL
Chuck_IO_File::writeFloat( t_CKFLOAT val
)
1872 if( !good2write() ) return 0;
1883 //-----------------------------------------------------------------------------
1884 // name: writeString()
1885 // desc: write string
1886 //-----------------------------------------------------------------------------
1887 t_CKBOOL
Chuck_IO_File::writeString( const string
& val
)
1890 if( !good2read() ) return 0;
1901 //-----------------------------------------------------------------------------
1902 // name: writeLine()
1904 //-----------------------------------------------------------------------------
1905 t_CKBOOL
Chuck_IO_File::writeLine( const string
& val
)
1908 if( !good2read() ) return 0;
1911 m_io
<< val
<< endl
;
1920 //-----------------------------------------------------------------------------
1922 // desc: read next 32 bits, return as int
1923 //-----------------------------------------------------------------------------
1924 t_CKINT
Chuck_IO_File::read32i()
1932 //-----------------------------------------------------------------------------
1934 // desc: read next 24 bits, return as int
1935 //-----------------------------------------------------------------------------
1936 t_CKINT
Chuck_IO_File::read24i()
1944 //-----------------------------------------------------------------------------
1946 // desc: read next 16 bits, return as int
1947 //-----------------------------------------------------------------------------
1948 t_CKINT
Chuck_IO_File::read16i()
1956 //-----------------------------------------------------------------------------
1958 // desc: return next 8 bits, return as int
1959 //-----------------------------------------------------------------------------
1960 t_CKINT
Chuck_IO_File::read8i()
1968 //-----------------------------------------------------------------------------
1970 // desc: return next 32-bits as (binary) single float
1971 //-----------------------------------------------------------------------------
1972 t_CKSINGLE
Chuck_IO_File::read32f()
1980 //-----------------------------------------------------------------------------
1982 // desc: return next 64-bits as (binary) double float
1983 //-----------------------------------------------------------------------------
1984 t_CKDOUBLE
Chuck_IO_File::read64f()