BASH   24

parmacs

Guest on 29th June 2022 07:49:13 AM

  1. #!/bin/sh
  2. # This is a shell archive, meaning:
  3. # 1. Remove everything above the #!/bin/sh line.
  4. # 2. Save the resulting text in a file.
  5. # 3. Execute the file with /bin/sh (not csh) to create the files:
  6. #       .
  7. # This archive created: Thu Sep  8 10:55:58 1988
  8. export PATH; PATH=/bin:$PATH
  9. echo shar: extracting "'README'" '(1260 characters)'
  10. if test -f 'README'
  11. then
  12.         echo shar: over-writing existing file "'README'"
  13. fi
  14. sed 's/^X//' << \SHAR_EOF > 'README'
  15. XThis is an implementation of the shared-memory constructs from ANL Parmacs
  16. X(Lusk, Overbeek, et.al.) in C++.  It illustrates how C++ can be used to build
  17. Xparallel programming constructs, and numerous advantages over the ANL M4
  18. Ximplementation.  These advantages include extensibility, strong type
  19. Xchecking, ease of readability and use, and use of an object-oriented
  20. Xlanguage.
  21. X
  22. XThe code includes the classes and header files for all the shared-memory
  23. Xparmacs constructs (eg, BasicLock, Monitor, Barrier, Getsub, Askfor), and
  24. Xseveral useful derived classes (LeakLast, LeakOne, SimpleQ, GeneralQ).  There
  25. Xare also a set of simple examples.  The code should compile with AT&T C++
  26. Xv1.2.1, and uses the Sequent parallel programming library (-lpps).
  27. X
  28. XNo documentation is included yet, although the code is reasonably documented
  29. Xand is (hopefully) sufficient.  The author (Bob Beck of Sequent) has a paper
  30. Xdescribing this work submitted for publication; when this is available, a
  31. Xreference will be included with the code.
  32. X
  33. XDirect questions, comments, problems, additions, etc, to:
  34. X
  35. X                               Bob Beck
  36. X                               Principal Engineer
  37. X                               Sequent Computer Systems
  38. X                               15450 SW Koll Parkway
  39. X                               Beaverton, Oregon  97006-6063
  40. X                               ...{anlams,tektronix,ogcvax}!sequent!rbk
  41. X                               (503)626-5700
  42. SHAR_EOF
  43. if test 1260 -ne "`wc -c 'README'`"
  44. then
  45.         echo shar: error transmitting "'README'" '(should have been 1260 characters)'
  46. fi
  47. echo shar: extracting "'Makefile'" '(495 characters)'
  48. if test -f 'Makefile'
  49. then
  50.         echo shar: over-writing existing file "'Makefile'"
  51. fi
  52. sed 's/^X//' << \SHAR_EOF > 'Makefile'
  53. XP=&
  54. X
  55. XDEST/usr/local/c++/parmacs
  56. X
  57. XCCFLAGS=-O -Y
  58. X
  59. X.SUFFIXES:     .C
  60. X
  61. X.C.o:; CC ${CCFLAGS} -c $?
  62. X
  63. XLIB=   libparmacs.a
  64. XLIBOBJS=parmacs.o shnew.o shdelete.o slist.o main.o pinit.o pfinish.o
  65. X
  66. Xall:   ${LIB}
  67. X
  68. X${LIB}:$P      ${LIBOBJS}
  69. X       ar rcv $@ ${LIBOBJS}; \
  70. X       ranlib $@
  71. X
  72. Xinstall: all PCC
  73. X       -mkdir ${DEST}
  74. X       -rm -f ${DEST}/*
  75. X       cp ${LIB} *.h ${DEST}
  76. X       sed "s;DEST;${DEST};" < PCC > ${DEST}/PCC
  77. X       chmod +x ${DEST}/PCC
  78. X       ranlib ${DEST}/${LIB}
  79. X
  80. Xdoc:
  81. X       /usr/imagen/bin/itpf -x parmacs.ms
  82. X
  83. Xclean:
  84. X       rm -f *.c *.o *.a *.out core
  85. SHAR_EOF
  86. if test 495 -ne "`wc -c 'Makefile'`"
  87. then
  88.         echo shar: error transmitting "'Makefile'" '(should have been 495 characters)'
  89. fi
  90. echo shar: extracting "'PCC'" '(185 characters)'
  91. if test -f 'PCC'
  92. then
  93.         echo shar: over-writing existing file "'PCC'"
  94. fi
  95. sed 's/^X//' << \SHAR_EOF > 'PCC'
  96. X#! /bin/sh
  97. X# PCC -- Compile "parallel" C++ code that uses the parmacs classes.
  98. X# -Y ==> make all static data shared.
  99. X
  100. XPARDIR=DEST
  101. Xexec CC -Y -I${PARDIR} $* ${PARDIR}/libparmacs.a -lpps
  102. SHAR_EOF
  103. if test 185 -ne "`wc -c 'PCC'`"
  104. then
  105.         echo shar: error transmitting "'PCC'" '(should have been 185 characters)'
  106. fi
  107. chmod +x 'PCC'
  108. if test ! -d 'examples'
  109. then
  110.         echo shar: creating directory "'examples'"
  111.         mkdir 'examples'
  112. fi
  113. echo shar: entering directory "'examples'"
  114. cd 'examples'
  115. echo shar: extracting "'af.C'" '(1140 characters)'
  116. if test -f 'af.C'
  117. then
  118.         echo shar: over-writing existing file "'af.C'"
  119. fi
  120. sed 's/^X//' << \SHAR_EOF > 'af.C'
  121. X/*
  122. X * Simple example of Askfor monitor with derived class.  Monitor manages
  123. X * queued structure instances, each representing a unit of work.
  124. X */
  125. X
  126. X#include <stream.h>
  127. X#include <parmacs.h>
  128. X
  129. Xstruct elt     {
  130. X       elt*    e_next;
  131. X       int     e_work;
  132. X};
  133. X
  134. Xclass  work : public Askfor {
  135. X       elt*    queue;                          // queue of work
  136. X       int     getprob(void*& prob) {          // problem get'er
  137. X                       elt*    work;
  138. X                       if (queue != NULL) {            // Non-empty ==>
  139. X                               work = queue;           // de-queue work
  140. X                               queue = work->e_next;
  141. X                               prob = work;            // return pointer
  142. X                               return 1;               // and indicate got one
  143. X                       } else
  144. X                               return 0;               // no work available
  145. X               }
  146. Xpublic:
  147. X       work()          { queue = NULL; }
  148. X       void    putprob(elt* prob) {                    // add work.
  149. X                       enter();                        // lock the monitor.
  150. X                       prob->e_next = queue;           // queue the...
  151. X                       queue = prob;                   //      ...new work.
  152. X                       signal();                       // tell'em it's there.
  153. X               }
  154. X};
  155. X
  156. Xvoid
  157. Xpinit()
  158. X{
  159. X       set_numprocs(1);                        // force for the example
  160. X}
  161. X
  162. Xvoid
  163. Xpmain()
  164. X{
  165. X       int     i;
  166. X       elt*    prob;
  167. X       work    queue;
  168. X       int     N = 20;
  169. X
  170. X       for (i = 0; i < N; i++) {
  171. X               prob = new elt;
  172. X               prob->e_work = i;
  173. X               queue.putprob(prob);
  174. X       }
  175. X
  176. X       while (queue.getwork(prob) == 0) {
  177. X               cout << prob->e_work << " ";
  178. X               delete prob;
  179. X       }
  180. X
  181. X       cout << "\n";
  182. X}
  183. SHAR_EOF
  184. if test 1140 -ne "`wc -c 'af.C'`"
  185. then
  186.         echo shar: error transmitting "'af.C'" '(should have been 1140 characters)'
  187. fi
  188. echo shar: extracting "'gQ.C'" '(617 characters)'
  189. if test -f 'gQ.C'
  190. then
  191.         echo shar: over-writing existing file "'gQ.C'"
  192. fi
  193. sed 's/^X//' << \SHAR_EOF > 'gQ.C'
  194. X/*
  195. X * Demonstrate use of GeneralQ monitor.
  196. X */
  197. X
  198. X#include <stream.h>
  199. X#include <workQ.h>
  200. X
  201. Xstruct coord   {
  202. X       int     x, y;
  203. X       coord(int X, int Y)     { x = X; y = Y; }
  204. X};
  205. X
  206. Xvoid
  207. Xpinit()
  208. X{
  209. X       set_numprocs(1);                        // force for the example
  210. X}
  211. X
  212. Xvoid
  213. Xpmain(int argc, char **argv)
  214. X{
  215. X       int     i;
  216. X       coord*  prob;
  217. X       GeneralQ queue;
  218. X       int     N = 100;
  219. X
  220. X       if (argc > 1)
  221. X               N = atoi(argv[1]);
  222. X
  223. X       queue.set_cache(2*N);
  224. X
  225. X       for (i = 0; i < N; i++) {
  226. X               // queue.append(new coord(i, i*i));
  227. X               queue.insert(new coord(i, i*i));
  228. X       }
  229. X
  230. X       while (queue.getwork(prob) == 0) {
  231. X               cout << prob->x << " " << prob->y << "\n";
  232. X               if (prob->x == 20)
  233. X                       queue.probend();
  234. X               delete prob;
  235. X       }
  236. X}
  237. SHAR_EOF
  238. if test 617 -ne "`wc -c 'gQ.C'`"
  239. then
  240.         echo shar: error transmitting "'gQ.C'" '(should have been 617 characters)'
  241. fi
  242. echo shar: extracting "'gs.C'" '(262 characters)'
  243. if test -f 'gs.C'
  244. then
  245.         echo shar: over-writing existing file "'gs.C'"
  246. fi
  247. sed 's/^X//' << \SHAR_EOF > 'gs.C'
  248. X/*
  249. X * Simple example of Getsub monitor.  Can run in parallel.
  250. X */
  251. X
  252. X#include <stream.h>
  253. X#include <parmacs.h>
  254. X
  255. Xint    N = 20;
  256. XGetsub Index(1, N);
  257. X
  258. Xvoid
  259. Xpmain()
  260. X{
  261. X       int     i;
  262. X
  263. X       while (i = Index()) {
  264. X               cout << i << "\n";
  265. X       }
  266. X
  267. X       while (i = Index()) {
  268. X               cout << i << " ";
  269. X       }
  270. X}
  271. SHAR_EOF
  272. if test 262 -ne "`wc -c 'gs.C'`"
  273. then
  274.         echo shar: error transmitting "'gs.C'" '(should have been 262 characters)'
  275. fi
  276. echo shar: extracting "'gsaf.C'" '(712 characters)'
  277. if test -f 'gsaf.C'
  278. then
  279.         echo shar: over-writing existing file "'gsaf.C'"
  280. fi
  281. sed 's/^X//' << \SHAR_EOF > 'gsaf.C'
  282. X/*
  283. X * Getsub implemented as an Askfor monitor, to demonstrate generality of Askfor.
  284. X */
  285. X
  286. X#include <stream.h>
  287. X#include <parmacs.h>
  288. X
  289. Xclass  getsub : Askfor {
  290. X       int     min, max, sub;
  291. X       int     getprob(void*& prob) {
  292. X                       if (sub <= max) {
  293. X                               *(int*)prob = sub++;
  294. X                               return 1;
  295. X                       } else
  296. X                               return 0;
  297. X               }
  298. X       void    reset() { sub = min; }
  299. Xpublic:
  300. X       int     next() {
  301. X                       int     sub;
  302. X                       if (getwork(&sub) == 0)
  303. X                               return sub;
  304. X                       else
  305. X                               return min-1;
  306. X               }
  307. X       getsub(int Min, int Max, int Nproc = 0) : (Nproc) {
  308. X                       sub = min = Min;
  309. X                       max = Max;
  310. X               }
  311. X       int     operator()()    { return next(); }
  312. X};
  313. X
  314. Xint    N = 20;
  315. Xgetsub Index(1, N);
  316. X
  317. Xvoid
  318. Xpmain()
  319. X{
  320. X       int     i;
  321. X
  322. X       while (i = Index()) {
  323. X               cout << i << "\n";
  324. X       }
  325. X
  326. X       while (i = Index()) {
  327. X               cout << i << " ";
  328. X       }
  329. X}
  330. SHAR_EOF
  331. if test 712 -ne "`wc -c 'gsaf.C'`"
  332. then
  333.         echo shar: error transmitting "'gsaf.C'" '(should have been 712 characters)'
  334. fi
  335. echo shar: extracting "'sQ.C'" '(635 characters)'
  336. if test -f 'sQ.C'
  337. then
  338.         echo shar: over-writing existing file "'sQ.C'"
  339. fi
  340. sed 's/^X//' << \SHAR_EOF > 'sQ.C'
  341. X/*
  342. X * Demonstrate use of SimpleQ monitor.
  343. X */
  344. X
  345. X#include <stream.h>
  346. X#include <workQ.h>
  347. X
  348. Xstruct coord : SimpleLink {            // must be derived from SimpleLink
  349. X       int     x, y;
  350. X       coord(int X, int Y)     { x = X; y = Y; }
  351. X};
  352. X
  353. Xvoid
  354. Xpinit()
  355. X{
  356. X       set_numprocs(1);                        // force for the example
  357. X}
  358. X
  359. Xvoid
  360. Xpmain(int argc, char **argv)
  361. X{
  362. X       int     i;
  363. X       coord*  prob;
  364. X       SimpleQ queue;
  365. X       int     N = 100;
  366. X
  367. X       if (argc > 1)
  368. X               N = atoi(argv[1]);
  369. X
  370. X       for (i = 0; i < N; i++)
  371. X               // queue.append(new coord(i, i*i));
  372. X               queue.insert(new coord(i, i*i));
  373. X
  374. X       while (queue.getwork(prob) == 0) {
  375. X               cout << prob->x << " " << prob->y << "\n";
  376. X               if (prob->x == 20)
  377. X                       queue.probend();
  378. X               delete prob;
  379. X       }
  380. X}
  381. SHAR_EOF
  382. if test 635 -ne "`wc -c 'sQ.C'`"
  383. then
  384.         echo shar: error transmitting "'sQ.C'" '(should have been 635 characters)'
  385. fi
  386. echo shar: extracting "'prime.C'" '(1117 characters)'
  387. if test -f 'prime.C'
  388. then
  389.         echo shar: over-writing existing file "'prime.C'"
  390. fi
  391. sed 's/^X//' << \SHAR_EOF > 'prime.C'
  392. X/*
  393. X * Old dumb primes program again, this time in C++ with parmacs classes.
  394. X */
  395. X
  396. X#include <stream.h>
  397. X#include <parmacs.h>
  398. X
  399. Xvoid
  400. Xusage(char* prog)
  401. X{
  402. X       cerr << "Usage: " << prog << " numprimes\n";
  403. X       exit(1);
  404. X}
  405. X
  406. Xint    maxprime;                       // last interesting number
  407. Xchar*  array;                          // array filled to indicate prime-ness
  408. XGetsub*        candidates;                     // index iterator for prime candidates
  409. X
  410. Xvoid pinit(int argc, char **argv)
  411. X{
  412. X       if (argc < 2)
  413. X               usage(argv[0]);
  414. X       maxprime = atoi(argv[1]);
  415. X       array = new char[maxprime+1];
  416. X       candidates = new Getsub(1,maxprime);
  417. X}
  418. X
  419. X/*
  420. X * Illustrate auto-reset of "Getsub" monitor by initializing in parallel
  421. X * first, then determining the primes in parallel.
  422. X */
  423. X
  424. Xvoid pmain()
  425. X{
  426. X       register int i;
  427. X       int     isprime(int);
  428. X
  429. X       while (i = candidates->next())
  430. X               array[i] = ' ';
  431. X
  432. X       while (i = candidates->next())
  433. X               if (isprime(i))
  434. X                       array[i] = '*';
  435. X
  436. X       while (i = candidates->next())
  437. X               if (array[i] == '*')
  438. X                       cout << i << "\n";
  439. X}
  440. X
  441. Xisprime(int number)
  442. X{
  443. X       extern  double  sqrt(double);
  444. X
  445. X       if (number < 2)
  446. X               return 0;
  447. X
  448. X       int max = (int) sqrt(number) + 1;
  449. X       for (int i = 2; i < max; i++)
  450. X               if (number % i == 0)
  451. X                       return 0;
  452. X       return 1;
  453. X}
  454. SHAR_EOF
  455. if test 1117 -ne "`wc -c 'prime.C'`"
  456. then
  457.         echo shar: error transmitting "'prime.C'" '(should have been 1117 characters)'
  458. fi
  459. echo shar: extracting "'Makefile'" '(615 characters)'
  460. if test -f 'Makefile'
  461. then
  462.         echo shar: over-writing existing file "'Makefile'"
  463. fi
  464. sed 's/^X//' << \SHAR_EOF > 'Makefile'
  465. XP=&
  466. X
  467. XINCL=  -I..
  468. XCCFLAGS=-O -Y ${INCL}
  469. XHDRS=  ../parmacs.h ../slist.h ../workQ.h
  470. X
  471. X.SUFFIXES:     .C
  472. X
  473. X.C.o:; CC ${CCFLAGS} -c $<
  474. X
  475. XLIB=   ../libparmacs.a
  476. X
  477. XTESTS=         gs   af   gsaf   gQ   sQ   mQ   prime   ll   lo  
  478. XTESTOBJS=      gs.o af.o gsaf.o gQ.o sQ.o mQ.o prime.o ll.o lo.o
  479. X
  480. Xall:   testobjs testprogs
  481. X
  482. Xtestobjs:$P    ${TESTOBJS}
  483. X
  484. Xtestprogs:$P   ${TESTS}
  485. X
  486. X${TESTS}:
  487. X       CC -o $@ $@.o ${LIB} -lpps -lm
  488. X
  489. Xclean:
  490. X       rm -f ${TESTS} *.c *.o *.a a.out *.out *.dis core
  491. X
  492. Xgs:    gs.o ${LIB}
  493. Xaf:    af.o ${LIB}
  494. Xgsaf:  gsaf.o ${LIB}
  495. XgQ:    gQ.o ${LIB}
  496. XsQ:    sQ.o ${LIB}
  497. XmQ:    mQ.o ${LIB}
  498. Xprime: prime.o ${LIB}
  499. Xll:    ll.o ${LIB}
  500. Xlo:    lo.o ${LIB}
  501. X
  502. X${TESTOBJS}: ${HDRS}
  503. SHAR_EOF
  504. if test 615 -ne "`wc -c 'Makefile'`"
  505. then
  506.         echo shar: error transmitting "'Makefile'" '(should have been 615 characters)'
  507. fi
  508. echo shar: extracting "'mQ.C'" '(468 characters)'
  509. if test -f 'mQ.C'
  510. then
  511.         echo shar: over-writing existing file "'mQ.C'"
  512. fi
  513. sed 's/^X//' << \SHAR_EOF > 'mQ.C'
  514. X/*
  515. X * Simple example of Getsub loop creating work that's being consumed by
  516. X * a SimpleQ.
  517. X */
  518. X
  519. X#include <stream.h>
  520. X#include <workQ.h>
  521. X
  522. Xconst  int     N = 100;
  523. X
  524. XSimpleQ        queue;
  525. XGetsub Index(1,N);
  526. X
  527. Xstruct coord : SimpleLink {
  528. X       int     x, y;
  529. X       coord(int X, int Y)     { x = X; y = Y; }
  530. X};
  531. X
  532. Xvoid
  533. Xpmain()
  534. X{
  535. X       int     i;
  536. X       coord*  prob;
  537. X
  538. X       while (i = Index())
  539. X               queue.insert(new coord(i, i*i));
  540. X
  541. X       while (queue.getwork(prob) == 0) {
  542. X               cout << prob->x << " " << prob->y << "\n";
  543. X               delete prob;
  544. X       }
  545. X}
  546. SHAR_EOF
  547. if test 468 -ne "`wc -c 'mQ.C'`"
  548. then
  549.         echo shar: error transmitting "'mQ.C'" '(should have been 468 characters)'
  550. fi
  551. echo shar: extracting "'ll.C'" '(390 characters)'
  552. if test -f 'll.C'
  553. then
  554.         echo shar: over-writing existing file "'ll.C'"
  555. fi
  556. sed 's/^X//' << \SHAR_EOF > 'll.C'
  557. X/*
  558. X * Example of LeakLast barrier.
  559. X */
  560. X
  561. X#include <stream.h>
  562. X#include <parmacs.h>
  563. X
  564. XBasicLock      l;
  565. XLeakLast       last;
  566. X
  567. Xint    getpid();
  568. X
  569. Xvoid pmain()
  570. X{
  571. X       l.lock();
  572. X       cout << getpid() << "\n";
  573. X       l.unlock();
  574. X
  575. X       if (last.enter())
  576. X               cout << "last in was " << getpid() << "\n";
  577. X       if (last.enter())
  578. X               cout << "last in was " << getpid() << "\n";
  579. X       if (last.enter())
  580. X               cout << "last in was " << getpid() << "\n";
  581. X}
  582. SHAR_EOF
  583. if test 390 -ne "`wc -c 'll.C'`"
  584. then
  585.         echo shar: error transmitting "'ll.C'" '(should have been 390 characters)'
  586. fi
  587. echo shar: extracting "'lo.C'" '(439 characters)'
  588. if test -f 'lo.C'
  589. then
  590.         echo shar: over-writing existing file "'lo.C'"
  591. fi
  592. sed 's/^X//' << \SHAR_EOF > 'lo.C'
  593. X/*
  594. X * Example of LeakOne barrier.
  595. X */
  596. X
  597. X#include <stream.h>
  598. X#include <parmacs.h>
  599. X
  600. XBasicLock      l;
  601. XLeakOne                one;
  602. X
  603. Xint    getpid();
  604. X
  605. Xvoid pmain()
  606. X{
  607. X       l.lock();
  608. X       cout << getpid() << "\n";
  609. X       l.unlock();
  610. X
  611. X       if (one.enter()) {
  612. X               cout << "winner was " << getpid() << "\n";
  613. X               one.exit();
  614. X       }
  615. X       if (one.enter()) {
  616. X               cout << "winner was " << getpid() << "\n";
  617. X               one.exit();
  618. X       }
  619. X       if (one.enter()) {
  620. X               cout << "winner was " << getpid() << "\n";
  621. X               one.exit();
  622. X       }
  623. X}
  624. SHAR_EOF
  625. if test 439 -ne "`wc -c 'lo.C'`"
  626. then
  627.         echo shar: error transmitting "'lo.C'" '(should have been 439 characters)'
  628. fi
  629. echo shar: done with directory "'examples'"
  630. cd ..
  631. echo shar: extracting "'main.C'" '(737 characters)'
  632. if test -f 'main.C'
  633. then
  634.         echo shar: over-writing existing file "'main.C'"
  635. fi
  636. sed 's/^X//' << \SHAR_EOF > 'main.C'
  637. X#ifndef        lint
  638. Xstatic char    rcsid[] = "$Header: main.C 1.3 88/04/04 $";
  639. X#endif
  640. X
  641. X/*
  642. X * main.C
  643. X *     Main program for parallel-C++ with parmacs classes.
  644. X */
  645. X
  646. X/* $Log:       main.C,v $
  647. X */
  648. X
  649. X/*
  650. X * main()
  651. X *     Calls pinit() while still serial (to allow for any initializations),
  652. X *     then m_fork()'s pmain() (ie, starts parallel execution).
  653. X *     When done, kill slaves and call pfinish() (again, serial).
  654. X */
  655. X
  656. Xtypedef        void (*VF)(...);
  657. X
  658. Xvoid   m_fork(VF, ...);
  659. Xvoid   m_kill_procs();
  660. X
  661. Xvoid   pinit(int, char**);
  662. Xvoid   pmain(int, char**);
  663. Xvoid   pfinish();
  664. X
  665. Xmain(int argc, char** argv)
  666. X{
  667. X       pinit(argc, argv);                      // serial initializations
  668. X       m_fork(pmain, argc, argv);              // parallel main program
  669. X       m_kill_procs();                         // kill slave processes
  670. X       pfinish();                              // serial finish up
  671. X}
  672. SHAR_EOF
  673. if test 737 -ne "`wc -c 'main.C'`"
  674. then
  675.         echo shar: error transmitting "'main.C'" '(should have been 737 characters)'
  676. fi
  677. echo shar: extracting "'parmacs.C'" '(5162 characters)'
  678. if test -f 'parmacs.C'
  679. then
  680.         echo shar: over-writing existing file "'parmacs.C'"
  681. fi
  682. sed 's/^X//' << \SHAR_EOF > 'parmacs.C'
  683. X#ifndef        lint
  684. Xstatic char    rcsid[] = "$Header: parmacs.C 1.8 88/04/04 $";
  685. X#endif
  686. X
  687. X/*
  688. X * parmacs.C
  689. X *     Out of line implementations of parmacs classes.  See parmacs.h
  690. X *     for class definitions.
  691. X *
  692. X * Much of the parmacs classes are inline's for efficiency.
  693. X */
  694. X
  695. X/* $Log:       parmacs.C,v $
  696. X */
  697. X
  698. X#include "parmacs.h"
  699. X
  700. X/*
  701. X * set_numprocs()
  702. X *     Arrange for given number processors.  Returns -1 if can't satisfy.
  703. X *
  704. X * Typically called in pinit() to arrange # processors before creating
  705. X * monitors.  If not called, the environment variable PARALLEL is used,
  706. X * and if that isn't defined, a system default.  Once number processors
  707. X * is determined, subsequent calls to set_numprocs() fail.
  708. X */
  709. X
  710. Xextern int     m_numprocs;             // -lpps stores default here
  711. Xextern int     m_set_procs(int);       // -lpps set # processes
  712. Xextern int     m_get_numprocs();       // -lpps return # processes
  713. X
  714. Xset_numprocs(int Nprocs)
  715. X{
  716. X       if (m_numprocs > 0)             // can't change once set.
  717. X               return -1;
  718. X       else
  719. X               return m_set_procs(Nprocs);
  720. X}
  721. X
  722. X/*
  723. X * get_numprocs()
  724. X *     Return number of processors to use.
  725. X *     Uses a default if none yet declared (see above).
  726. X *
  727. X * Augments -lpps by importing environment variable PARALLEL.
  728. X *
  729. X * 1st call sets number of processes to use to PARALLEL environment variable or
  730. X * -lpps default.  Use set_numprocs() to set a different number of processors
  731. X * (but must call before call get_numprocs()).
  732. X */
  733. X
  734. Xint
  735. Xget_numprocs()
  736. X{
  737. X       extern  char*   getenv(char*);
  738. X       extern  int     atoi(char*);
  739. X
  740. X       if (m_numprocs < 0) {
  741. X               char*   parallel;
  742. X               if (parallel = getenv("PARALLEL"))
  743. X                       m_set_procs(atoi(parallel));    // should check error
  744. X               else
  745. X                       m_set_procs(m_get_numprocs());  // shouldn't error
  746. X       }
  747. X       return m_numprocs;
  748. X}
  749. X
  750. X/*
  751. X * BasicLock is completely defined with inlines.
  752. X */
  753. X
  754. X/*
  755. X * Basic monitor, including "wait" and "signal".
  756. X */
  757. X
  758. XMonitor::Monitor()
  759. X{
  760. X       qcount = 0;                     // noone queued yet
  761. X       qwait.lock();                   // waiting lock starts out locked
  762. X}
  763. X
  764. X/*
  765. X * Simple barrier.
  766. X *     Block all callers until all have enterred.
  767. X */
  768. X
  769. XBarrier::Barrier(int Nprocs)           // initialize # processes
  770. X{
  771. X       nprocs = (Nprocs ? Nprocs : get_numprocs());
  772. X}
  773. X
  774. X/*
  775. X * Subscript server monitor:
  776. X *     Return next subscript, atomicly.
  777. X */
  778. X
  779. XGetsub::Getsub(int Min, int Max, int Nprocs) : (Nprocs)
  780. X{
  781. X       sub = min = Min;
  782. X       max = Max;
  783. X}
  784. X
  785. X/*
  786. X * Generalized "askfor" monitor:
  787. X *     Base class for general work queueing and distribution.
  788. X */
  789. X
  790. XAskfor::Askfor(int Nprocs) : (Nprocs)
  791. X{
  792. X       done = 0;
  793. X}
  794. X
  795. X/*
  796. X * Askfor::getwork()
  797. X *     Get a unit of work from monitor, return code indicates success.
  798. X *
  799. X * Return code =
  800. X *     0       == got work
  801. X *     -1      == program done
  802. X *     1       == ran out of problems
  803. X *     > 1     == someone declared problem done
  804. X *
  805. X * See parmacs.h and the book for more details.
  806. X *
  807. X * Implementation uses one "done" flag, not 2 as in ANL macros.  The done
  808. X * flag is encoded to allow fewer tests in "hot path":  done == 0 ==> still
  809. X * active;  done = -1 ==> "program" done;  done > 0 ==> "problem" done.
  810. X * probend() and progend() functions insure encoding stays valid.
  811. X */
  812. X
  813. XAskfor::getwork(void*& prob)
  814. X{
  815. X       /*
  816. X        * If problem marked "done" wait here for others to arrive (or
  817. X        * "program" done).  Otherwise, loop looking for work until
  818. X        * "done" is set.
  819. X        */
  820. X       enter();
  821. X       if (done > 0) {
  822. X               if (!lastin())
  823. X                       wait();
  824. X       } else while (!done) {
  825. X               /*
  826. X                * Try to get a problem (unit of work).  If got one, return.
  827. X                * getprob() is defined in a derived class, fills out prob or
  828. X                * what prob points at (depends on derived class definition).
  829. X                */
  830. X               if (getprob(prob)) {    // true if got work, filled out `prob'
  831. X                       signal();       // try next, if appropriate
  832. X                       return 0;       // ==> got a problem
  833. X               }
  834. X               /*
  835. X                * Didn't get a problem.  If last one to arrive, declare
  836. X                * problem done (ran out of work to do).  Otherwise, wait for
  837. X                * new problem(s) or problem/program done.
  838. X                */
  839. X               if (lastin())
  840. X                       done = 1;
  841. X               else
  842. X                       wait();
  843. X       }
  844. X       /*
  845. X        * Land here if problem or program declared done.
  846. X        *
  847. X        * While blocked in wait() above, program can be declared "done".  But
  848. X        * once "signal" loop starts, no process can re-enter the monitor
  849. X        * (since signal() gives it to a waiter rather then exit monitor).  Thus
  850. X        * if done > 0 here (problem-done) it cannot be set < 0 (program-done).
  851. X        *
  852. X        * Note that once declare program-done (done < 0), done is never reset.
  853. X        */
  854. X       if (done < 0) {                 // "program" done
  855. X               signal();               // let others see it
  856. X               return -1;              // ==> program done
  857. X       }
  858. X       /*
  859. X        * Problem was declared done.  The wait()'s above form a barrier; last
  860. X        * in the barrier starts the exodus.  Last out of the barrier resets
  861. X        * the problem logic and problem-done flag; must be last out to
  862. X        * insure all see the problem-done code before it's reset.
  863. X        */
  864. X       int return_code = done;
  865. X       if (lastout()) {                // last to leave...
  866. X               reset();                // turns out...
  867. X               done = 0;               // the lights.
  868. X       }
  869. X       signal();
  870. X       return return_code;
  871. X}
  872. X
  873. Xvoid
  874. XAskfor::probend(int code)              // declare sub-problem done
  875. X{
  876. X       enter();
  877. X       if (done == 0 && code > 0) done = code;
  878. X       exit();
  879. X}
  880. X
  881. Xvoid
  882. XAskfor::progend()              // declare entire program done
  883. X{
  884. X       enter();
  885. X       done = -1;              // unconditionally set < 0 ==> program done
  886. X       signal();
  887. X}
  888. X
  889. XAskfor::getprob(void*&)                        // default returns no problem exists
  890. X{
  891. X       return 0;
  892. X}
  893. X
  894. Xvoid
  895. XAskfor::reset()                                // default logic-reset function (NOP)
  896. X{
  897. X       /*NOP*/
  898. X}
  899. SHAR_EOF
  900. if test 5162 -ne "`wc -c 'parmacs.C'`"
  901. then
  902.         echo shar: error transmitting "'parmacs.C'" '(should have been 5162 characters)'
  903. fi
  904. echo shar: extracting "'parmacs.h'" '(8494 characters)'
  905. if test -f 'parmacs.h'
  906. then
  907.         echo shar: over-writing existing file "'parmacs.h'"
  908. fi
  909. sed 's/^X//' << \SHAR_EOF > 'parmacs.h'
  910. X/*
  911. X * $Header: parmacs.h 1.10 88/04/04 $
  912. X *
  913. X * parmacs.h
  914. X *     C++ classes defining basic parallel programming constructs.
  915. X *
  916. X * All locking constructs are spin-lock based (eg, busy-wait).
  917. X *
  918. X * Flavor of interface/implementation comes from the Argonne Labs "parmacs"
  919. X * m4 macros, described in the book "Portable Programs for Parallel
  920. X * Processors", Lusk, Overbeek, et.al., Holt, Rinehart, and Winston, Inc,
  921. X * ISBN 0-03-014153-2.
  922. X */
  923. X
  924. X/* $Log:       parmacs.h,v $
  925. X */
  926. X
  927. X#ifndef        PARMACS_H
  928. X#define        PARMACS_H
  929. X
  930. X/*
  931. X * set_numprocs()
  932. X *     Arrange for given number processors.  Returns -1 if can't satisfy.
  933. X *
  934. X * Typically called in pinit() to arrange # processors before creating
  935. X * monitors.  If not called, the environment variable PARALLEL is used,
  936. X * and if that isn't defined, a system default.  Once number processors
  937. X * is determined, subsequent calls to set_numprocs() are ignored.
  938. X *
  939. X * get_numprocs()
  940. X *     Return number of processes(ors) in use.
  941. X *     Uses a default if none yet declared (see above).
  942. X */
  943. X
  944. Xextern set_numprocs(int Nprocs);
  945. Xextern get_numprocs();
  946. X
  947. X/*
  948. X * Basic Locks -- low-level mutual-exclusion.
  949. X *
  950. X * Implemented via Sequent Parallel Programming Library spin-locks.
  951. X */
  952. X
  953. Xtypedef        unsigned char slock_t;
  954. X
  955. Xconst  slock_t S_UNLOCKED      = 0;
  956. Xconst  slock_t S_LOCKED        = 1;
  957. X
  958. Xextern void    s_lock(slock_t*);               // From -lpps
  959. Xextern void    s_unlock(slock_t*);             // From -lpps
  960. X
  961. Xclass  BasicLock {
  962. X       slock_t mutex;
  963. Xpublic:
  964. X       void    lock()          { s_lock(&mutex); }
  965. X       void    unlock()        { s_unlock(&mutex); }
  966. X               BasicLock()     { mutex = S_UNLOCKED; }
  967. X};
  968. X
  969. X/*
  970. X * Basic monitor, including "wait" and "signal".
  971. X *
  972. X * signal() passes ownership of monitor to a wait()'ing process.
  973. X */
  974. X
  975. Xclass  Monitor {
  976. X       BasicLock mutex;
  977. X       BasicLock qwait;
  978. X       int     qcount;
  979. Xpublic:
  980. X       Monitor();
  981. X       void    enter()         { mutex.lock(); }
  982. X       void    exit()          { mutex.unlock(); }
  983. X       void    wait()          { ++qcount; exit(); qwait.lock(); --qcount; }
  984. X       void    signal()        { if (qcount > 0) qwait.unlock(); else exit(); }
  985. X       int     qlen()          { return qcount; }
  986. X};
  987. X
  988. X/*
  989. X * Simple barrier.
  990. X *     Block all callers until all have enterred.
  991. X *
  992. X * Initialized with number of processes involved.  Automatically resets.
  993. X *
  994. X * Protected interface lastin() allows derived class to have barrier function
  995. X * with atomic reset by last process to enter.  lastin() returns true if caller
  996. X * is last to enter the barrier, else false.  Expected use in derived class is:
  997. X *
  998. X *             if (lastin()) {
  999. X *                     reset derived class;
  1000. X *                     signal();
  1001. X *             } else
  1002. X *                     wait();
  1003. X */
  1004. X
  1005. Xclass  Barrier : public Monitor {      // portable one-at-a-time barrier
  1006. X       int     nprocs;                 // # participating processes
  1007. Xprotected:
  1008. X       int     lastin();               // caller would be last to enter??
  1009. X       int     lastout();              // caller would be last to leave??
  1010. Xpublic:
  1011. X       Barrier(int Nprocs = 0);
  1012. X       void    wait();                 // "block" at barrier, wait for others
  1013. X};
  1014. X
  1015. Xinline int Barrier::lastin()   { return qlen() == nprocs-1; }
  1016. Xinline int Barrier::lastout()  { return qlen() == 0; }
  1017. X
  1018. Xinline void
  1019. XBarrier::wait()
  1020. X{
  1021. X       enter();                        // lock up monitor
  1022. X       if (!lastin())                  // !last in ==>
  1023. X               Monitor::wait();        //      wait for last
  1024. X       signal();                       // start'em (or let next) going
  1025. X}
  1026. X
  1027. X/*
  1028. X * LeakLast
  1029. X *     Barrier that leaks last caller.
  1030. X *
  1031. X * Last one to "enter" the barrier starts other leaving and returns indication
  1032. X * it is the last in.  All are concurrent once last one has entered.
  1033. X *
  1034. X * Typical use is:
  1035. X *     LeakLast onlyone;
  1036. X *     if (onlyone.enter())
  1037. X *             // only one does this
  1038. X *     // all do this
  1039. X *     if (onlyone.enter())
  1040. X *             // only one does this (maybe different one than first time)
  1041. X *     // all do this
  1042. X */
  1043. X
  1044. Xclass  LeakLast : Barrier {
  1045. Xpublic:
  1046. X       LeakLast(int Nprocs = 0) : (Nprocs) {}
  1047. X       int     enter();
  1048. X};
  1049. X
  1050. Xinline int
  1051. XLeakLast::enter()
  1052. X{
  1053. X       Monitor::enter();                       // lock up monitor
  1054. X       if (lastin()) {                         // last one in ...
  1055. X               Monitor::signal();              //      let others go
  1056. X               return 1;                       //      and let caller know
  1057. X       } else {                                // otherwise ...
  1058. X               Monitor::wait();                //      wait for last one
  1059. X               Monitor::signal();              //      let next go.
  1060. X               return 0;                       // wasn't last one in
  1061. X       }
  1062. X}
  1063. X
  1064. X/*
  1065. X * LeakOne
  1066. X *     Barrier that leaks one caller, others wait for it to say it's finished.
  1067. X *
  1068. X * Typical use is:
  1069. X *     LeakOne onlyone;
  1070. X *     if (onlyone.enter()) {
  1071. X *             // only one does this
  1072. X *             onlyone.exit();
  1073. X *     }
  1074. X *     // all do this
  1075. X *
  1076. X * This is typically used for initialization code that must only be done
  1077. X * once, before other processes can continue; for example, allocation
  1078. X * of new dynamic variables.
  1079. X *
  1080. X * Implementation has the first to enter do the work while others enter
  1081. X * the barrier queue (better parallelism).
  1082. X */
  1083. X
  1084. Xclass  LeakOne : Barrier {
  1085. X       int     firstin;                        // flag telling if first in
  1086. Xpublic:
  1087. X       LeakOne(int Nprocs = 0) : (Nprocs) { firstin = 1; }
  1088. X       int     enter();
  1089. X       void    exit();
  1090. X};
  1091. X
  1092. Xinline int
  1093. XLeakOne::enter()
  1094. X{
  1095. X       Monitor::enter();                       // lock up monitor
  1096. X       if (firstin) {                          // first one in ...
  1097. X               firstin = 0;                    //      marks it as so
  1098. X               Monitor::exit();                //      lets others queue
  1099. X               return 1;                       //      and does the work.
  1100. X       } else {                                // otherwise ...
  1101. X               if (lastin())                   //      last in...
  1102. X                       firstin = 1;            //              resets flag.
  1103. X               else                            //      otherwise...
  1104. X                       Monitor::wait();        //              wait for last.
  1105. X               Monitor::signal();              //      let next go.
  1106. X               return 0;                       // wasn't last one in
  1107. X       }
  1108. X}
  1109. X
  1110. Xinline void
  1111. XLeakOne::exit()
  1112. X{
  1113. X       Monitor::enter();                       // lock up monitor
  1114. X       if (lastin()) {                         // last one in ...
  1115. X               firstin = 1;                    //      resets flag
  1116. X       } else {                                // otherwise ...
  1117. X               Monitor::wait();                //      wait for last one
  1118. X       }
  1119. X       Monitor::signal();                      // let next go.
  1120. X}
  1121. X
  1122. X/*
  1123. X * Subscript server monitor:
  1124. X *     Return next subscript, atomicly.
  1125. X *
  1126. X * Each call to next() returns next subscript, atomicly.
  1127. X * When "done", all callers block at a barrier, and return min-1 after
  1128. X * all have arrived.  Automatically resets.
  1129. X *
  1130. X * Operator "()" interface to next() is also provided; eg,
  1131. X *     Getsub index(1,N,Nprocs);
  1132. X *     while (i = index()) { ... }
  1133. X */
  1134. X
  1135. Xclass  Getsub : Barrier {
  1136. X       int     min, max;               // min and max subscripts
  1137. X       int     sub;                    // next subscript to return
  1138. X       void    wait();                 // avoid confusion with Barrier::wait
  1139. Xpublic:
  1140. X       Getsub(int Min, int Max, int Nprocs = 0);
  1141. X       int     next();                 // return next subscript, or min-1
  1142. X       int     operator()();           // nice interface to next()
  1143. X};
  1144. X
  1145. Xinline void Getsub::wait() { Monitor::wait(); }
  1146. X
  1147. Xinline int
  1148. XGetsub::next()
  1149. X{
  1150. X       int     val;
  1151. X
  1152. X       enter();                        // lock up monitor
  1153. X       if (sub <= max) {               // have more left...
  1154. X               val = sub++;            // return next.
  1155. X               exit();                 // done.
  1156. X       } else {                        // no more left...
  1157. X               val = min - 1;          // return min-1.
  1158. X               if (lastin())           // last one in...
  1159. X                       sub = min;      //      resets subscript
  1160. X               else                    // !last one in...
  1161. X                       wait();         //      ==> wait for last to arrive
  1162. X               signal();               // start'em (or let next) going
  1163. X       }
  1164. X       return val;
  1165. X}
  1166. X
  1167. Xinline int Getsub::operator()()        { return next(); }
  1168. X
  1169. X/*
  1170. X * Generalized "askfor" monitor:
  1171. X *     Base class for general work queueing and distribution.
  1172. X *
  1173. X * Primary use is to call getwork() with a single argument, a pointer to a some
  1174. X * structure type; getwork() will dequeue one of these from the monitor and
  1175. X * assign its address to the pointer argument.  getwork() returns 0 if a
  1176. X * problem (piece of work) has been allocated, -1 for "program done", or > 0
  1177. X * for "sub-problem" done (value can be passed to probdone()).
  1178. X *
  1179. X * Derived-class provides "get-problem" logic and "reset" logic (if any):
  1180. X *
  1181. X *     getprob(prob)
  1182. X *             If there is work to do, dequeue a piece of work, make `prob'
  1183. X *             point at it, and return true.  Else, return false.
  1184. X *
  1185. X *     reset()
  1186. X *             Is called between sub-problems, when all processes have blocked
  1187. X *             at a barrier.  reset() should do whatever necessary to set up
  1188. X *             for next sub-problem.  This is optional.
  1189. X *
  1190. X * These are called with the monitor already locked; ie, don't call enter(),
  1191. X * as this will deadlock.
  1192. X *
  1193. X * Other utility functions available to derived class:
  1194. X *
  1195. X *     enter()
  1196. X *             Lock the monitor.
  1197. X *
  1198. X *     exit()
  1199. X *             Unlock the monitor.
  1200. X *
  1201. X * Semantics are very close to the ANL ASKFOR macro.  See the book for more
  1202. X * information/details.
  1203. X *
  1204. X * Note that C++ constructs reference if needed, so this works:
  1205. X *
  1206. X *     int     i, rc;
  1207. X *     askfor  x;
  1208. X *     rc = x.getwork(&i);
  1209. X *
  1210. X * This allows getprob() to fill out *prob, not just the pointer.  In the
  1211. X * above case, getprob() would do something like *(int*)prob = <whatever>;
  1212. X */
  1213. X
  1214. Xclass  Askfor : public Barrier {
  1215. X       int     done;                   // problem/program done flag
  1216. X       virtual getprob(void*&);        // get-problem function
  1217. X       virtual void reset();           // logic-reset function
  1218. X       void    wait();                 // avoid confusion with Barrier::wait
  1219. Xpublic:
  1220. X       Askfor(int Nprocs=0);           // constructor
  1221. X       int     getwork(void*&);        // get a unit of work
  1222. X       void    probend(int=2);         // declare sub-problem done
  1223. X       void    progend();              // declare program done
  1224. X};
  1225. X
  1226. Xinline void Askfor::wait() { Monitor::wait(); }
  1227. X
  1228. X#endif PARMACS_H
  1229. SHAR_EOF
  1230. if test 8494 -ne "`wc -c 'parmacs.h'`"
  1231. then
  1232.         echo shar: error transmitting "'parmacs.h'" '(should have been 8494 characters)'
  1233. fi
  1234. echo shar: extracting "'pfinish.C'" '(388 characters)'
  1235. if test -f 'pfinish.C'
  1236. then
  1237.         echo shar: over-writing existing file "'pfinish.C'"
  1238. fi
  1239. sed 's/^X//' << \SHAR_EOF > 'pfinish.C'
  1240. X#ifndef        lint
  1241. Xstatic char    rcsid[] = "$Header: pfinish.C 1.2 88/04/04 $";
  1242. X#endif
  1243. X
  1244. X/*
  1245. X * pfinish.C
  1246. X *     Default (NOP) parallel-finish-up function.
  1247. X */
  1248. X
  1249. X/* $Log:       pfinish.C,v $
  1250. X */
  1251. X
  1252. X/*
  1253. X * pfinish()
  1254. X *     Called (single-stream) from main() after parallel program is done.
  1255. X *
  1256. X * This provides a (NOP) default, in case user program has no need for
  1257. X * such finish-ups.
  1258. X */
  1259. X
  1260. Xvoid
  1261. Xpfinish()
  1262. X{
  1263. X       /*NOP*/
  1264. X}
  1265. SHAR_EOF
  1266. if test 388 -ne "`wc -c 'pfinish.C'`"
  1267. then
  1268.         echo shar: error transmitting "'pfinish.C'" '(should have been 388 characters)'
  1269. fi
  1270. echo shar: extracting "'pinit.C'" '(361 characters)'
  1271. if test -f 'pinit.C'
  1272. then
  1273.         echo shar: over-writing existing file "'pinit.C'"
  1274. fi
  1275. sed 's/^X//' << \SHAR_EOF > 'pinit.C'
  1276. X#ifndef        lint
  1277. Xstatic char    rcsid[] = "$Header: pinit.C 1.2 88/04/04 $";
  1278. X#endif
  1279. X
  1280. X/*
  1281. X * pinit.C
  1282. X *     Default (NOP) parallel-init function.
  1283. X */
  1284. X
  1285. X/* $Log:       pinit.C,v $
  1286. X */
  1287. X
  1288. X/*
  1289. X * pinit()
  1290. X *     Called from main() while still serial.
  1291. X *
  1292. X * This provides a (NOP) default, in case user program has no need for
  1293. X * such initializations.
  1294. X */
  1295. X
  1296. Xvoid
  1297. Xpinit(int, char**)
  1298. X{
  1299. X       /*NOP*/
  1300. X}
  1301. SHAR_EOF
  1302. if test 361 -ne "`wc -c 'pinit.C'`"
  1303. then
  1304.         echo shar: error transmitting "'pinit.C'" '(should have been 361 characters)'
  1305. fi
  1306. echo shar: extracting "'shdelete.C'" '(272 characters)'
  1307. if test -f 'shdelete.C'
  1308. then
  1309.         echo shar: over-writing existing file "'shdelete.C'"
  1310. fi
  1311. sed 's/^X//' << \SHAR_EOF > 'shdelete.C'
  1312. X#ifndef        lint
  1313. Xstatic char    rcsid[] = "$Header: shdelete.C 1.2 88/04/04 $";
  1314. X#endif
  1315. X
  1316. X/*
  1317. X * shdelete.C
  1318. X *     Shared-memory version of the delete operator.
  1319. X */
  1320. X
  1321. X/* $Log:       shdelete.C,v $
  1322. X */
  1323. X
  1324. Xextern shfree(char*);
  1325. Xextern void operator delete(void* p)
  1326. X{
  1327. X       if (p) shfree( (char*)p );
  1328. X}
  1329. SHAR_EOF
  1330. if test 272 -ne "`wc -c 'shdelete.C'`"
  1331. then
  1332.         echo shar: error transmitting "'shdelete.C'" '(should have been 272 characters)'
  1333. fi
  1334. echo shar: extracting "'shnew.C'" '(434 characters)'
  1335. if test -f 'shnew.C'
  1336. then
  1337.         echo shar: over-writing existing file "'shnew.C'"
  1338. fi
  1339. sed 's/^X//' << \SHAR_EOF > 'shnew.C'
  1340. X#ifndef        lint
  1341. Xstatic char    rcsid[] = "$Header: shnew.C 1.2 88/04/04 $";
  1342. X#endif
  1343. X
  1344. X/*
  1345. X * shnew.C
  1346. X *     Shared-memory version of the new operator.
  1347. X */
  1348. X
  1349. X/* $Log:       shnew.C,v $
  1350. X */
  1351. X
  1352. Xtypedef void (*PFVV)();
  1353. X
  1354. Xextern PFVV _new_handler;
  1355. X
  1356. Xextern void* operator new(long size)
  1357. X{
  1358. X       extern char* shmalloc(unsigned);
  1359. X       char* p;
  1360. X
  1361. X       while ( (p=shmalloc(unsigned(size)))==0 ) {
  1362. X               if(_new_handler)
  1363. X                       (*_new_handler)();
  1364. X               else
  1365. X                       return 0;
  1366. X       }
  1367. X       return (void*)p;
  1368. X}
  1369. SHAR_EOF
  1370. if test 434 -ne "`wc -c 'shnew.C'`"
  1371. then
  1372.         echo shar: error transmitting "'shnew.C'" '(should have been 434 characters)'
  1373. fi
  1374. echo shar: extracting "'slist.C'" '(2374 characters)'
  1375. if test -f 'slist.C'
  1376. then
  1377.         echo shar: over-writing existing file "'slist.C'"
  1378. fi
  1379. sed 's/^X//' << \SHAR_EOF > 'slist.C'
  1380. X#ifndef        lint
  1381. Xstatic char    rcsid[] = "$Header: slist.C 1.3 88/04/04 $";
  1382. X#endif
  1383. X
  1384. X/*
  1385. X * slist.C
  1386. X *     C++ classes defining singly-linked-list manipulations.
  1387. X *
  1388. X * Motivated from C++ book, Sec 7.3 (not identical, though).
  1389. X */
  1390. X
  1391. X/* $Log:       slist.C,v $
  1392. X */
  1393. X
  1394. X#include "slist.h"
  1395. X
  1396. X/*
  1397. X * SimpleList
  1398. X *     Simple, efficient singly-linked list.  No dynamic allocation.
  1399. X *     Queue-able structures must be derived from "SimpleLink".
  1400. X *
  1401. X * Keeps circular list, with pointer to tail of list.  tail->next is
  1402. X * head of the list.
  1403. X *
  1404. X * append() and insert() are inline for efficiency.
  1405. X */
  1406. X
  1407. XSimpleLink*                    // inline here causes C++ bug (generates bad C)
  1408. XSimpleList::get()
  1409. X{
  1410. X       if (tail == NULL)
  1411. X               return NULL;
  1412. X       else {
  1413. X               SimpleLink* head = tail->next;
  1414. X               if (head == tail)
  1415. X                       tail = NULL;
  1416. X               else
  1417. X                       tail->next = head->next;
  1418. X               return head;
  1419. X       }
  1420. X}
  1421. X
  1422. Xvoid
  1423. XSimpleList::clear()
  1424. X{
  1425. X       register SimpleLink* p;
  1426. X
  1427. X       while (p = get()) delete p;     // delete all queued objects
  1428. X}
  1429. X
  1430. X/*
  1431. X * GenList
  1432. X *     More general singly-linked list.
  1433. X *     Can enqueue any object, and given object multiple times.
  1434. X *
  1435. X * Keeps circular list, with pointer to tail of list.  tail->next is
  1436. X * head of the list.
  1437. X *
  1438. X * Uses queueing object (GenListQ), and caches these for efficiency.
  1439. X */
  1440. X
  1441. X/*inline*/                             // C++ gens bad C if inline here
  1442. XGenListQ*
  1443. XGenList::newQ(void* Obj, GenListQ* p)  // return new initialized Q object
  1444. X{
  1445. X       if (num_cache > 0) {
  1446. X               register GenListQ* Qobj = cache;
  1447. X               cache = Qobj->next;
  1448. X               --num_cache;
  1449. X               Qobj->next = p;
  1450. X               Qobj->obj = Obj;
  1451. X               return Qobj;
  1452. X       } else
  1453. X               return new GenListQ(Obj, p);
  1454. X}
  1455. X
  1456. X/*inline*/                     // inline here causes C++ bug (generates bad C)
  1457. Xvoid*
  1458. XGenList::get()                 // get entry from head of Q, NULL if none
  1459. X{
  1460. X       if (tail == NULL)
  1461. X               return NULL;
  1462. X       else {
  1463. X               GenListQ* head = tail->next;
  1464. X               if (head == tail)
  1465. X                       tail = NULL;
  1466. X               else
  1467. X                       tail->next = head->next;
  1468. X               void* val = head->obj;
  1469. X               cacheQ(head);
  1470. X               return val;
  1471. X       }
  1472. X}
  1473. X
  1474. Xvoid
  1475. XGenList::clear()                               // delete all queued objects
  1476. X{
  1477. X       register void*  p;
  1478. X
  1479. X       while (p = get()) delete p;
  1480. X}
  1481. X
  1482. Xvoid
  1483. XGenList::set_cache(int Max)            // set size of cache
  1484. X{
  1485. X       while (num_cache > Max) {
  1486. X               GenListQ* Qobj = cache;
  1487. X               cache = Qobj->next;
  1488. X               --num_cache;
  1489. X               delete Qobj;
  1490. X       }
  1491. X       max_cache = Max;
  1492. X}
  1493. X
  1494. XGenList::GenList(int MaxCache)         // initialize the Q
  1495. X{
  1496. X       cache = tail = NULL;
  1497. X       max_cache = MaxCache;
  1498. X       num_cache = 0;
  1499. X}
  1500. X
  1501. XGenList::~GenList()                    // destroy the Q
  1502. X{
  1503. X       clear();                        // clear the Q
  1504. X       set_cache(0);                   // purge the cache
  1505. X}
  1506. SHAR_EOF
  1507. if test 2374 -ne "`wc -c 'slist.C'`"
  1508. then
  1509.         echo shar: error transmitting "'slist.C'" '(should have been 2374 characters)'
  1510. fi
  1511. echo shar: extracting "'slist.h'" '(2887 characters)'
  1512. if test -f 'slist.h'
  1513. then
  1514.         echo shar: over-writing existing file "'slist.h'"
  1515. fi
  1516. sed 's/^X//' << \SHAR_EOF > 'slist.h'
  1517. X/*
  1518. X * $Header: slist.h 1.2 88/04/04 $
  1519. X *
  1520. X * slist.h
  1521. X *     C++ classes defining singly-linked-list manipulations.
  1522. X *
  1523. X * Motivated from C++ book, Sec 7.3 (not identical, though).
  1524. X */
  1525. X
  1526. X/* $Log:       slist.h,v $
  1527. X */
  1528. X
  1529. X#ifndef        SLIST_H
  1530. X#define        SLIST_H
  1531. X
  1532. X#ifndef NULL
  1533. X#define NULL   0
  1534. X#endif
  1535. X
  1536. X/*
  1537. X * SimpleList
  1538. X *     Simple, efficient singly-linked list.  No dynamic allocation.
  1539. X *     Queue-able structures must be derived from "SimpleLink".
  1540. X *
  1541. X * Keeps circular list, with pointer to tail of list.  tail->next is
  1542. X * head of the list.
  1543. X *
  1544. X * append() and insert() are inline for efficiency.
  1545. X */
  1546. X
  1547. Xstruct SimpleLink      {
  1548. X       SimpleLink*     next;
  1549. X};
  1550. X
  1551. Xclass  SimpleList      {
  1552. X       SimpleLink*     tail;                   // end of list
  1553. Xpublic:
  1554. X       void            clear();                // purge the queue
  1555. X       void            insert(SimpleLink*);    // insert at head of list
  1556. X       void            append(SimpleLink*);    // append at end of list
  1557. X       SimpleLink*     get();                  // get an entry, NULL if none
  1558. X       SimpleList()    { tail = NULL; }        // initialize
  1559. X       ~SimpleList()   { clear(); }            // destroy
  1560. X};
  1561. X
  1562. Xinline void
  1563. XSimpleList::insert(SimpleLink* elt)
  1564. X{
  1565. X       if (tail) {
  1566. X               elt->next = tail->next;
  1567. X               tail->next = elt;
  1568. X       } else {
  1569. X               tail = elt;
  1570. X               elt->next = elt;
  1571. X       }
  1572. X}
  1573. X
  1574. Xinline void
  1575. XSimpleList::append(SimpleLink* elt)
  1576. X{
  1577. X       if (tail) {
  1578. X               elt->next = tail->next;
  1579. X               tail = tail->next = elt;
  1580. X       } else {
  1581. X               tail = elt;
  1582. X               elt->next = elt;
  1583. X       }
  1584. X}
  1585. X
  1586. X/*
  1587. X * GenList
  1588. X *     More general singly-linked list.
  1589. X *     Can enqueue any object, and given object multiple times.
  1590. X *
  1591. X * Keeps circular list, with pointer to tail of list.  tail->next is
  1592. X * head of the list.
  1593. X *
  1594. X * Uses queueing object (GenListQ), and caches these for efficiency.
  1595. X */
  1596. X
  1597. Xstruct GenListQ        {
  1598. X       GenListQ*       next;
  1599. X       void*           obj;
  1600. X       GenListQ(void* ent, GenListQ* p) { obj = ent; next = p; }
  1601. X};
  1602. X
  1603. Xclass  GenList {
  1604. X       GenListQ*       tail;                   // end of list; head=tail->next
  1605. X       int             max_cache;              // max Q objects in cache
  1606. X       int             num_cache;              // current # Q objects cached
  1607. X       GenListQ*       cache;                  // cache of Q objects
  1608. X       GenListQ*       newQ(void*, GenListQ*); // return initialized Q object
  1609. X       void            cacheQ(GenListQ*);      // cache or delete a Q object
  1610. Xpublic:
  1611. X       void            set_cache(int);         // set max size of cache
  1612. X       void            clear();                // purge the queue
  1613. X       void            insert(void*);          // insert at head of Q
  1614. X       void            append(void*);          // append at end of Q
  1615. X       void*           get();                  // get an entry, NULL if none
  1616. X       GenList(int MaxCache = 0);              // initialize (cacheing off)
  1617. X       ~GenList();                             // destroy the Q
  1618. X};
  1619. X
  1620. Xinline void
  1621. XGenList::cacheQ(GenListQ* Qobj)                // add to cache or delete, as approp
  1622. X{
  1623. X       if (num_cache < max_cache) {
  1624. X               Qobj->next = cache;
  1625. X               cache = Qobj;
  1626. X               ++num_cache;
  1627. X       } else
  1628. X               delete Qobj;
  1629. X}
  1630. X
  1631. Xinline void
  1632. XGenList::insert(void* elt)             // insert at head of Q
  1633. X{
  1634. X       if (tail)
  1635. X               tail->next = newQ(elt, tail->next);
  1636. X       else {
  1637. X               tail = newQ(elt, NULL);
  1638. X               tail->next = tail;
  1639. X       }
  1640. X}
  1641. X
  1642. Xinline void
  1643. XGenList::append(void* elt)             // insert at tail of Q
  1644. X{
  1645. X       if (tail)
  1646. X               tail = tail->next = newQ(elt, tail->next);
  1647. X       else {
  1648. X               tail = newQ(elt, NULL);
  1649. X               tail->next = tail;
  1650. X       }
  1651. X}
  1652. X
  1653. X#endif SLIST_H
  1654. SHAR_EOF
  1655. if test 2887 -ne "`wc -c 'slist.h'`"
  1656. then
  1657.         echo shar: error transmitting "'slist.h'" '(should have been 2887 characters)'
  1658. fi
  1659. echo shar: extracting "'workQ.h'" '(1833 characters)'
  1660. if test -f 'workQ.h'
  1661. then
  1662.         echo shar: over-writing existing file "'workQ.h'"
  1663. fi
  1664. sed 's/^X//' << \SHAR_EOF > 'workQ.h'
  1665. X/*
  1666. X * $Header: workQ.h 1.2 88/04/04 $
  1667. X *
  1668. X * workQ.h
  1669. X *     C++ classes defining work-queue constructs on top of Askfor monitor.
  1670. X */
  1671. X
  1672. X/* $Log:       workQ.h,v $
  1673. X */
  1674. X
  1675. X#ifndef        WORKQ_H
  1676. X#define        WORKQ_H
  1677. X
  1678. X#include "parmacs.h"                   // basic parallel-programming support
  1679. X#include "slist.h"                     // singly-linked list support
  1680. X
  1681. X/*
  1682. X * SimpleQ
  1683. X *     Simple work queue monitor -- uses SimpleList for queueing.
  1684. X *
  1685. X * Enqueues work elements derived from "work" base class.
  1686. X * Simple/fast (no dynamic allocation of queueing objects), but limited
  1687. X * in that work structures must be derived from "SimpleLink".
  1688. X *
  1689. X * Adds own getwork() interface for more type checking over Askfor.
  1690. X */
  1691. X
  1692. Xclass  SimpleQ : public Askfor {
  1693. X       SimpleList queue;
  1694. X       int     getprob(void*& prob) {
  1695. X                       return (prob = (void*)queue.get()) != NULL;
  1696. X               }
  1697. X       void    reset()         { queue.clear(); }
  1698. Xpublic:
  1699. X       int     getwork(SimpleLink*& prob) { return Askfor::getwork(prob); }
  1700. X       void    append(SimpleLink* prob) { enter(); queue.append(prob); signal(); }
  1701. X       void    insert(SimpleLink* prob) { enter(); queue.insert(prob); signal(); }
  1702. X       SimpleQ(int Nprocs = 0) : (Nprocs) {}
  1703. X};
  1704. X
  1705. X/*
  1706. X * GeneralQ
  1707. X *     More General work queue monitor -- uses GenList for queueing.
  1708. X *
  1709. X * Enqueues any type of object.  Allows cacheing of queueing objects for
  1710. X * efficiency.
  1711. X *
  1712. X * Takes and produces (void*) objects.  More strongly typed interfaces can
  1713. X * be derived from GeneralQ.
  1714. X */
  1715. X
  1716. Xclass  GeneralQ : public Askfor {
  1717. X       GenList queue;
  1718. X       int     getprob(void*& prob)    { return (prob = queue.get()) != NULL; }
  1719. X       void    reset()                 { queue.clear(); }
  1720. Xpublic:
  1721. X       void    append(void* prob) { enter(); queue.append(prob); signal(); }
  1722. X       void    insert(void* prob) { enter(); queue.insert(prob); signal(); }
  1723. X       void    set_cache(int Max) { enter(); queue.set_cache(Max); exit(); }
  1724. X       GeneralQ(int MaxCache = 0, int Nprocs = 0) : (Nprocs) {
  1725. X                       queue.set_cache(MaxCache);
  1726. X               }
  1727. X};
  1728. X
  1729. X#endif WORKQ_H
  1730. SHAR_EOF
  1731. if test 1833 -ne "`wc -c 'workQ.h'`"
  1732. then
  1733.         echo shar: error transmitting "'workQ.h'" '(should have been 1833 characters)'
  1734. fi
  1735. #       End of shell archive
  1736. exit 0

Raw Paste


Login or Register to edit or fork this paste. It's free.