Remove "no doc" pragma from private function in Error module

/*
 * Copyright 2004-2015 Cray Inc.
 * Other additional copyright holders may be indicated within.
 *
 * The entirety of this work is licensed under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*

   Support for error handling.

   This module helps to handle errors. In particular, it enables routines
   to return a syserr - encoding an error state - and then contains routines
   that can be provided a syserr in order to print out a useful error message.

   This module defines the type syserr, which can encode an error code or an
   error message. This type can be returned from routines generating an error.

   The IO module uses these routines in a way that supports error inspection
   and also rapid prototyping. Most routines in the IO module have two forms.
   In one form, an error (of type syserr) is returned in an out error argument.
   In the second form, no error is returned, and instead the task will halt
   with a fatal error if an error is encountered.

 */
module Error {

use SysBasic;

// here's what we need from Sys
private extern proc sys_strerror_syserr_str(error:syserr, out err_in_strerror:err_t):c_string;

/* This function takes in a string and returns it in double-quotes,
   with internal double-quotes escaped with backslash.
   */
pragma "no doc"
proc quote_string(s:string, len:ssize_t) {
  extern const QIO_STRING_FORMAT_CHPL: uint(8);
  extern proc qio_quote_string(s:uint(8), e:uint(8), f:uint(8),
                               ptr: c_string, len:ssize_t,
                               ref ret:c_string, ti: c_void_ptr): syserr;
  extern proc qio_strdup(s: c_string): c_string;

  var ret: c_string;
  // 34 is ASCII double quote
  var err: syserr = qio_quote_string(34:uint(8), 34:uint(8),
                                    QIO_STRING_FORMAT_CHPL,
                                    s.c_str(), len, ret, c_nil);

  // This doesn't handle the case where ret==NULL as did the previous
  // version in QIO, but I'm not sure how that was used.

  if err then return qio_strdup("<error>");
  return ret;
}

/* Halt with a useful message if there was an error. Do nothing if the error
   argument does not indicate an error occured. The error message printed
   when halting will describe the error passed and msg will be appended to it.

   :arg error: the error object
   :arg msg: extra information to print after the error description
 */
proc ioerror(error:syserr, msg:string)
{
  if( error ) {
    var errstr:c_string;
    var strerror_err:err_t = ENOERR;
    errstr = sys_strerror_syserr_str(error, strerror_err);
    __primitive("chpl_error", errstr + " " + msg.c_str());
  }
}

/* Halt with a useful message if there was an error. Do nothing if the error
   argument does not indicate an error occured. The error message printed
   when halting will describe the error passed and msg will be appended to it,
   along with the path related to the error (for example, the path to a file
   which could not be opened).

   :arg error: the error object
   :arg msg: extra information to print after the error description
   :arg path: a path to print out that is related to the error
 */
proc ioerror(error:syserr, msg:string, path:string)
{
  if( error ) {
    var errstr:c_string;
    var quotedpath:c_string;
    var strerror_err:err_t = ENOERR;
    errstr = sys_strerror_syserr_str(error, strerror_err);
    quotedpath = quote_string(path, path.length:ssize_t);
    __primitive("chpl_error", errstr + " " + msg.c_str() + " with path " + quotedpath);
  }
}

/* Halt with a useful message if there was an error. Do nothing if the error
   argument does not indicate an error occured. The error message printed
   when halting will describe the error passed and msg will be appended to it,
   along with the path and file offset related to the error. For example, this
   routine might indicate a file format error at a particular location.

   :arg error: the error object
   :arg msg: extra information to print after the error description
   :arg path: a path to print out that is related to the error
   :arg offset: an offset to print out that is related to the error
 */
proc ioerror(error:syserr, msg:string, path:string, offset:int(64))
{
  if( error ) {
    var errstr:c_string;
    var quotedpath:c_string;
    var strerror_err:err_t = ENOERR;
    errstr = sys_strerror_syserr_str(error, strerror_err);
    quotedpath = quote_string(path, path.length:ssize_t);
    // TODO: Because the output of concatenation (+) is an allocated string,
    // this routine leaks like a sieve.
    __primitive("chpl_error", errstr + " " + msg.c_str() + " with path " + quotedpath + " offset " + offset:c_string_copy);
  }
}

/* Halt with a useful message. Instead of an error argument, this routine takes
   in an error string to report.
   The error message printed when halting will describe the error passed and
   msg will be appended to it, along with the path and file offset related to
   the error. For example, this routine might indicate a file format error at a
   particular location.

   This routine .

   :arg errstr: the error string
   :arg msg: extra information to print after the error description
   :arg path: a path to print out that is related to the error
   :arg offset: an offset to print out that is related to the error
 */
proc ioerror(errstr:string, msg:string, path:string, offset:int(64))
{
  var quotedpath:c_string;
  quotedpath = quote_string(path, path.length:ssize_t);
  // TODO: Because the output of concatenation (+) is an allocated string,
  // this routine leaks like a sieve.
  __primitive("chpl_error", errstr + " " + msg.c_str() + " with path " + quotedpath + " offset " + offset:c_string_copy);
}

/* Convert a syserr error code to a human-readable string describing that
   error.

   :arg errstr: the error string
   :returns: a string describing the error
 */
proc errorToString(error:syserr):string
{
  var errstr:c_string = "unknown"; // Why initialize this?
  var strerror_err:err_t = ENOERR;
  errstr = sys_strerror_syserr_str(error, strerror_err);
  return errstr;
}

}

/*
 * Copyright 2004-2015 Cray Inc.
 * Other additional copyright holders may be indicated within.
 *
 * The entirety of this work is licensed under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*

   Support for error handling.

   This module helps to handle errors. In particular, it enables routines
   to return a syserr - encoding an error state - and then contains routines
   that can be provided a syserr in order to print out a useful error message.

   This module defines the type syserr, which can encode an error code or an
   error message. This type can be returned from routines generating an error.

   The IO module uses these routines in a way that supports error inspection
   and also rapid prototyping. Most routines in the IO module have two forms.
   In one form, an error (of type syserr) is returned in an out error argument.
   In the second form, no error is returned, and instead the task will halt
   with a fatal error if an error is encountered.

 */
module Error {

use SysBasic;

// here's what we need from Sys
pragma "no doc"
private extern proc sys_strerror_syserr_str(error:syserr, out err_in_strerror:err_t):c_string;

/* This function takes in a string and returns it in double-quotes,
   with internal double-quotes escaped with backslash.
   */
pragma "no doc"
proc quote_string(s:string, len:ssize_t) {
  extern const QIO_STRING_FORMAT_CHPL: uint(8);
  extern proc qio_quote_string(s:uint(8), e:uint(8), f:uint(8),
                               ptr: c_string, len:ssize_t,
                               ref ret:c_string, ti: c_void_ptr): syserr;
  extern proc qio_strdup(s: c_string): c_string;

  var ret: c_string;
  // 34 is ASCII double quote
  var err: syserr = qio_quote_string(34:uint(8), 34:uint(8),
                                    QIO_STRING_FORMAT_CHPL,
                                    s.c_str(), len, ret, c_nil);

  // This doesn't handle the case where ret==NULL as did the previous
  // version in QIO, but I'm not sure how that was used.

  if err then return qio_strdup("<error>");
  return ret;
}

/* Halt with a useful message if there was an error. Do nothing if the error
   argument does not indicate an error occured. The error message printed
   when halting will describe the error passed and msg will be appended to it.

   :arg error: the error object
   :arg msg: extra information to print after the error description
 */
proc ioerror(error:syserr, msg:string)
{
  if( error ) {
    var errstr:c_string;
    var strerror_err:err_t = ENOERR;
    errstr = sys_strerror_syserr_str(error, strerror_err);
    __primitive("chpl_error", errstr + " " + msg.c_str());
  }
}

/* Halt with a useful message if there was an error. Do nothing if the error
   argument does not indicate an error occured. The error message printed
   when halting will describe the error passed and msg will be appended to it,
   along with the path related to the error (for example, the path to a file
   which could not be opened).

   :arg error: the error object
   :arg msg: extra information to print after the error description
   :arg path: a path to print out that is related to the error
 */
proc ioerror(error:syserr, msg:string, path:string)
{
  if( error ) {
    var errstr:c_string;
    var quotedpath:c_string;
    var strerror_err:err_t = ENOERR;
    errstr = sys_strerror_syserr_str(error, strerror_err);
    quotedpath = quote_string(path, path.length:ssize_t);
    __primitive("chpl_error", errstr + " " + msg.c_str() + " with path " + quotedpath);
  }
}

/* Halt with a useful message if there was an error. Do nothing if the error
   argument does not indicate an error occured. The error message printed
   when halting will describe the error passed and msg will be appended to it,
   along with the path and file offset related to the error. For example, this
   routine might indicate a file format error at a particular location.

   :arg error: the error object
   :arg msg: extra information to print after the error description
   :arg path: a path to print out that is related to the error
   :arg offset: an offset to print out that is related to the error
 */
proc ioerror(error:syserr, msg:string, path:string, offset:int(64))
{
  if( error ) {
    var errstr:c_string;
    var quotedpath:c_string;
    var strerror_err:err_t = ENOERR;
    errstr = sys_strerror_syserr_str(error, strerror_err);
    quotedpath = quote_string(path, path.length:ssize_t);
    // TODO: Because the output of concatenation (+) is an allocated string,
    // this routine leaks like a sieve.
    __primitive("chpl_error", errstr + " " + msg.c_str() + " with path " + quotedpath + " offset " + offset:c_string_copy);
  }
}

/* Halt with a useful message. Instead of an error argument, this routine takes
   in an error string to report.
   The error message printed when halting will describe the error passed and
   msg will be appended to it, along with the path and file offset related to
   the error. For example, this routine might indicate a file format error at a
   particular location.

   This routine .

   :arg errstr: the error string
   :arg msg: extra information to print after the error description
   :arg path: a path to print out that is related to the error
   :arg offset: an offset to print out that is related to the error
 */
proc ioerror(errstr:string, msg:string, path:string, offset:int(64))
{
  var quotedpath:c_string;
  quotedpath = quote_string(path, path.length:ssize_t);
  // TODO: Because the output of concatenation (+) is an allocated string,
  // this routine leaks like a sieve.
  __primitive("chpl_error", errstr + " " + msg.c_str() + " with path " + quotedpath + " offset " + offset:c_string_copy);
}

/* Convert a syserr error code to a human-readable string describing that
   error.

   :arg errstr: the error string
   :returns: a string describing the error
 */
proc errorToString(error:syserr):string
{
  var errstr:c_string = "unknown"; // Why initialize this?
  var strerror_err:err_t = ENOERR;
  errstr = sys_strerror_syserr_str(error, strerror_err);
  return errstr;
}

}


Some small formatting changes.

git-svn-id: 88467cb1fb04b8a755be7e1ee1026be4190196ef@7982 3a8e244f-b0f2-452b-bcba-4c88e055c3ca

module RARandomStream {
  param randWidth = 64;
  // would like to use randWidth here, but cannot
  type randType = uint(64);

  param hiRandBit = 0x1:randType << (randWidth-1);
  // BLC: would eventually like these to be params as well
  const bitDom = [0..randWidth),
        m2: [bitDom] randType = computeM2Vals(randWidth);

  iterator RAStream(numvals, start = 0:randType): randType {
    var val = getNthRandom(start);
    for i in 1..numvals {
      getNextRand(val);
      yield val;
    }
  }

  def getNthRandom(in n) {
    param period = 0x7fffffffffffffff/7;

    if (n == 0) then return 0x1;
    if (n > period) then n -= period;

    var ran: randType = 0x2;
    for i in [0..log2(n)) by -1 {
      var val: randType = 0;
      for j in bitDom do
        if ((ran >> j) & 1) then val ^= m2(j);
      ran = val;
      if ((n >> i) & 1) then getNextRand(ran);
    }
    return ran;
  }

  // BLC: would also like to see this fn inlined -- how to specify?
  def getNextRand(inout x) {
    param POLY:randType = 0x7;  // BLC: this cast should be unnecessary?
    x = (x << 1) ^ (if (x & hiRandBit) then POLY else 0);
  }

  iterator computeM2Vals(numVals): randType {
    var nextVal = 0x1: randType;
    for i in 1..numVals {
      yield nextVal;
      getNextRand(nextVal);
      getNextRand(nextVal);
    }
  }
}

module RARandomStream {
  param randWidth = 64;
  // would like to use randWidth here, but cannot
  type randType = uint(64);

  param hiRandBit = 0x1:randType << (randWidth-1);
  // BLC: would eventually like these to be params as well
  const bitDom = [0..randWidth),
        m2: [bitDom] randType = computeM2Vals(randWidth);

  iterator RAStream(numvals, start:randType = 0): randType {
    var val = getNthRandom(start);
    for i in 1..numvals {
      getNextRand(val);
      yield val;
    }
  }

  def getNthRandom(in n) {
    param period = 1317624576693539401;

    while (n & hiRandBit) do
      n += period;
    while (n > period) do
      n -= period;
    if (n == 0) then return 0x1;

    var ran: randType = 0x2;
    for i in [0..log2(n)) by -1 {
      var val: randType = 0;
      for j in bitDom do
        if ((ran >> j) & 1) then val ^= m2(j);
      ran = val;
      if ((n >> i) & 1) then getNextRand(ran);
    }
    return ran;
  }

  // BLC: would also like to see this fn inlined -- how to specify?
  def getNextRand(inout x) {
    param POLY:randType = 0x7;  // BLC: this cast should be unnecessary?
    x = (x << 1) ^ (if (x & hiRandBit) then POLY else 0);
  }

  iterator computeM2Vals(numVals): randType {
    var nextVal = 0x1: randType;
    for i in 1..numVals {
      yield nextVal;
      getNextRand(nextVal);
      getNextRand(nextVal);
    }
  }
}


Add explicit code to clean up GMP structure when done.

/* The Computer Language Benchmarks Game
   http://shootout.alioth.debian.org/

   contributed by Tom Hildebrandt, Brad Chamberlain, Lydia Duncan
   derived from the GNU C version by Bonzini, Bartlett, and Mellor
*/

use GMP;

config const n = 50;                // Compute n digits of Pi, 50 by default

proc main() {
  for (d,i) in zip(gen_digits(n), 1..) {
    write(d);
    if i % 10 == 0 then
      writeln("\t:",i);
  }
}

iter gen_digits(numDigits) {
  var numer, accum, denom, tmp1, tmp2: mpz_t;

  mpz_init_set_ui(numer, 1);               // numer = 1
  mpz_init_set_ui(accum, 0);               // accum = 0
  mpz_init_set_ui(denom, 1);               // denom = 1
  mpz_init(tmp1);                          // init tmp1
  mpz_init(tmp2);                          // init tmp2

  var k: c_ulong;
  for i in 1..numDigits {
    do {
      do {
        k += 1;
        const y2 = 2 * k + 1;

        //
        // Compute the next term
        //
        mpz_mul_2exp(tmp1, numer, 1);      // tmp1  = numer * 2
        mpz_add(accum, accum, tmp1);	   // accum += numer * 2
        mpz_mul_ui(accum, accum, y2);	   // accum *= (2k+1)
        mpz_mul_ui(numer, numer, k);       // numer *= k
        mpz_mul_ui(denom, denom, y2);      // denom *= (2k+1)

        //
        // Continue looping until the digit is ready
        //
      } while (mpz_cmp(numer, accum) > 0); // while numer > accum

      //
      // Compute (numer * 3 + accum)
      //
      mpz_mul_2exp(tmp1, numer, 1);        // tmp1 = numer * 2
      mpz_add(tmp1, tmp1, numer);          // tmp1 += numer
      mpz_add(tmp1, tmp1, accum);          // tmp1 += accum

      //
      // tmp1 = tmp1 / denom; tmp2 = tmp1 % denom
      //
      mpz_fdiv_qr(tmp1, tmp2, tmp1, denom);

      //
      // Now, if (numer * 3 + accum) % denom + numer
      // == (numer * 4 + accum) % denom
      //
      mpz_add(tmp2, tmp2, numer);
    } while (mpz_cmp(tmp2, denom) >= 0);   // while tmp2 >= denom

    //
    // compute and yield the digit, d
    //
    const d = mpz_get_ui(tmp1);            // get least significant digit
    yield d;

    //
    // eliminate digit d
    //
    mpz_submul_ui(accum, denom, d);        // accum = (accum - denom) * d
    mpz_mul_ui(accum, accum, 10);          // accum *= 10
    mpz_mul_ui(numer, numer, 10);          // numer *= 10
  }

  // Clean up when done.
  mpz_clear(numer);
  mpz_clear(accum);
  mpz_clear(denom);
  mpz_clear(tmp1);
  mpz_clear(tmp2);
}

/* The Computer Language Benchmarks Game
   http://shootout.alioth.debian.org/

   contributed by Tom Hildebrandt, Brad Chamberlain, Lydia Duncan
   derived from the GNU C version by Bonzini, Bartlett, and Mellor
*/

use GMP;

config const n = 50;                // Compute n digits of Pi, 50 by default

proc main() {
  for (d,i) in zip(gen_digits(n), 1..) {
    write(d);
    if i % 10 == 0 then
      writeln("\t:",i);
  }
}

iter gen_digits(numDigits) {
  var numer, accum, denom, tmp1, tmp2: mpz_t;

  mpz_init_set_ui(numer, 1);               // numer = 1
  mpz_init_set_ui(accum, 0);               // accum = 0
  mpz_init_set_ui(denom, 1);               // denom = 1
  mpz_init(tmp1);                          // init tmp1
  mpz_init(tmp2);                          // init tmp2

  var k: c_ulong;
  for i in 1..numDigits {
    do {
      do {
        k += 1;
        const y2 = 2 * k + 1;

        //
        // Compute the next term
        //
        mpz_mul_2exp(tmp1, numer, 1);      // tmp1  = numer * 2
        mpz_add(accum, accum, tmp1);	   // accum += numer * 2
        mpz_mul_ui(accum, accum, y2);	   // accum *= (2k+1)
        mpz_mul_ui(numer, numer, k);       // numer *= k
        mpz_mul_ui(denom, denom, y2);      // denom *= (2k+1)

        //
        // Continue looping until the digit is ready
        //
      } while (mpz_cmp(numer, accum) > 0); // while numer > accum

      //
      // Compute (numer * 3 + accum)
      //
      mpz_mul_2exp(tmp1, numer, 1);        // tmp1 = numer * 2
      mpz_add(tmp1, tmp1, numer);          // tmp1 += numer
      mpz_add(tmp1, tmp1, accum);          // tmp1 += accum

      //
      // tmp1 = tmp1 / denom; tmp2 = tmp1 % denom
      //
      mpz_fdiv_qr(tmp1, tmp2, tmp1, denom);

      //
      // Now, if (numer * 3 + accum) % denom + numer
      // == (numer * 4 + accum) % denom
      //
      mpz_add(tmp2, tmp2, numer);
    } while (mpz_cmp(tmp2, denom) >= 0);   // while tmp2 >= denom

    //
    // compute and yield the digit, d
    //
    const d = mpz_get_ui(tmp1);            // get least significant digit
    yield d;

    //
    // eliminate digit d
    //
    mpz_submul_ui(accum, denom, d);        // accum = (accum - denom) * d
    mpz_mul_ui(accum, accum, 10);          // accum *= 10
    mpz_mul_ui(numer, numer, 10);          // numer *= 10
  }
}


do allocation outside of lock

do allocation outside of lock

use GenHashKey32, Logging, Memory, IO, ReplicatedDist, Time;

type WordType = uint(32);

class Node {
  var word: WordType;
  var next: Node;
}

class PartitionInfo {
  var head: Node;
  var count: atomic int;

  var writerLock: atomicflag;

  inline proc lockWriter() {
    while writerLock.testAndSet() do chpl_task_yield();
  }

  inline proc unlockWriter() {
    writerLock.clear();
  }
}

// Separate the search parition strategy from locales.
// The reason that it's worth keeping partitions separate from locales is that
// it makes it easy to change locale counts without having to rebuild the partitions.
//
// Number of dimensions in the partition space.
// Each partition will be projected to a locale.
// If the number of partitions exceeds the number of locales,
// then the locales will be over-subscribed with possibly more than one
// partition per locale.
//
config const partitionDimensions = 16;

// Partition to locale mapping.  Zero-based to allow modulo to work conveniently.
const Space = {0..partitionDimensions-1};
const ReplicatedSpace = Space dmapped ReplicatedDist();
var Partitions: [ReplicatedSpace] PartitionInfo;

proc initPartitions() {
  var t: Timer;
  t.start();

  debug("Partitions");
  debug(Space);
  debug(ReplicatedSpace);
  debug(Partitions.size);
  debug(Partitions);

  for loc in Locales {
    on loc {
      for i in Partitions.domain {
        Partitions[i] = new PartitionInfo();
      }
    }
  }

  debug("Partitions [after init]");
  debug(Partitions);

  t.stop();
  timing("initialized partitions in ",t.elapsed(TimeUnits.microseconds), " microseconds");
}

inline proc partitionIdForWord(word: WordType): int {
  return genHashKey32(word) % partitionDimensions;
}

inline proc localeForWord(word: WordType): locale {
  return Locales[partitionIdForWord(word) % Locales.size];
}

// should be a local lookup
inline proc partitionInfoForWord(word: WordType): PartitionInfo {
  return Partitions[partitionIdForWord(word)];
}

// override method to make it easy to switch WordType from string to uint(32)
inline proc genHashKey32(x: uint(32)): uint(32) {
  return x;
}

// override method to make it easy to switch WordType from string to uint(32)
inline proc indexWord(word: string) {
  indexWord(genHashKey32(word));
}

proc indexWord(word: WordType) {
  // first move the locale that should have the word.  There may be more than one active partition on a single locale.
  on localeForWord(word) {
    // locally operate on the partition info that the word maps to
    local {
      var info = partitionInfoForWord(word);
      var newNode = new Node(word); // do allocation outside of lock
      info.lockWriter();
      newNode.next = info.head;
      info.head = newNode;
      info.unlockWriter();
      info.count.add(1);
      debug(Partitions);
    }
  }
}

proc main() {
  initPartitions();

  var t: Timer;
  t.start();

  var infile = open("words.txt", iomode.r);

  coforall word in infile.lines() {
    indexWord(word);
  }

  debug(Partitions);

  t.stop();
  timing("indexing complete in ",t.elapsed(TimeUnits.microseconds), " microseconds");
}

use GenHashKey32, Logging, Memory, IO, ReplicatedDist, Time;

type WordType = uint(32);

class Node {
  var word: WordType;
  var next: Node;
}

class PartitionInfo {
  var head: Node;
  var count: atomic int;

  var writerLock: atomicflag;

  inline proc lockWriter() {
    while writerLock.testAndSet() do chpl_task_yield();
  }

  inline proc unlockWriter() {
    writerLock.clear();
  }
}

// Separate the search parition strategy from locales.
// The reason that it's worth keeping partitions separate from locales is that
// it makes it easy to change locale counts without having to rebuild the partitions.
//
// Number of dimensions in the partition space.
// Each partition will be projected to a locale.
// If the number of partitions exceeds the number of locales,
// then the locales will be over-subscribed with possibly more than one
// partition per locale.
//
config const partitionDimensions = 16;

// Partition to locale mapping.  Zero-based to allow modulo to work conveniently.
const Space = {0..partitionDimensions-1};
const ReplicatedSpace = Space dmapped ReplicatedDist();
var Partitions: [ReplicatedSpace] PartitionInfo;

proc initPartitions() {
  var t: Timer;
  t.start();

  debug("Partitions");
  debug(Space);
  debug(ReplicatedSpace);
  debug(Partitions.size);
  debug(Partitions);

  for loc in Locales {
    on loc {
      for i in Partitions.domain {
        Partitions[i] = new PartitionInfo();
      }
    }
  }

  debug("Partitions [after init]");
  debug(Partitions);

  t.stop();
  timing("initialized partitions in ",t.elapsed(TimeUnits.microseconds), " microseconds");
}

inline proc partitionIdForWord(word: WordType): int {
  return genHashKey32(word) % partitionDimensions;
}

inline proc localeForWord(word: WordType): locale {
  return Locales[partitionIdForWord(word) % Locales.size];
}

// should be a local lookup
inline proc partitionInfoForWord(word: WordType): PartitionInfo {
  return Partitions[partitionIdForWord(word)];
}

// override method to make it easy to switch WordType from string to uint(32)
inline proc genHashKey32(x: uint(32)): uint(32) {
  return x;
}

// override method to make it easy to switch WordType from string to uint(32)
inline proc indexWord(word: string) {
  indexWord(genHashKey32(word));
}

proc indexWord(word: WordType) {
  // first move the locale that should have the word.  There may be more than one active partition on a single locale.
  on localeForWord(word) {
    // locally operate on the partition info that the word maps to
    local {
      var info = partitionInfoForWord(word);
      info.lockWriter();
      info.head = new Node(word, info.head);
      info.unlockWriter();
      info.count.add(1);
      debug(Partitions);
    }
  }
}

proc main() {
  initPartitions();

  var t: Timer;
  t.start();

  var infile = open("words.txt", iomode.r);

  coforall word in infile.lines() {
    indexWord(word);
  }

  debug(Partitions);

  t.stop();
  timing("indexing complete in ",t.elapsed(TimeUnits.microseconds), " microseconds");
}


Simple (harmless) change to see if SVN is still with me.

git-svn-id: 88467cb1fb04b8a755be7e1ee1026be4190196ef@19042 3a8e244f-b0f2-452b-bcba-4c88e055c3ca

use ChapelBase;
use ChapelIO;
use ChapelArray;
use DefaultRectangular;
use DefaultAssociative;

/*
   This code keeps track of tasks, their state, and where they
   spawned from.

   The taks information is used to generate a task report (optionally
   displayed when the user Ctrl+C's out of the program).

   The type chpl_taskID_t is a primitve type defined in the include
   files for each tasking layer.

*/

enum taskState { pending, active, suspended };

//
// This represents a currently running task.  The state, lineno, and
// filename members should be obvious; tl_info is information belonging
// to the tasking layer.
//
// If we included the parent in this, the print method could topologically
// sort the tasks and indent to show the parent/child relationships, which
// might be very nice.
//
record chpldev_Task {
  var state     : taskState;
  var lineno    : uint(32);
  var filename  : string;
  var tl_info   : uint(64);
}

var chpldev_taskTableD : domain(chpl_taskID_t, parSafe=false);
var chpldev_taskTable : [chpldev_taskTableD] chpldev_Task;

export proc chpldev_taskTable_add(taskID   : chpl_taskID_t,
                                  lineno   : uint(32),
                                  filename : string,
                                  tl_info  : uint(64))
{
  if(!chpldev_taskTableD.member(taskID)) {
    // This must be serial to avoid deadlock in a coforall. <hilde>
    serial true do
      chpldev_taskTableD.add(taskID);
  }
  chpldev_taskTable[taskID] = new chpldev_Task(taskState.pending,
                                               lineno, filename, tl_info);
}

export proc chpldev_taskTable_remove(taskID : chpl_taskID_t)
{
  // This must also be serial
  serial true do
    chpldev_taskTableD.remove(taskID);
}

export proc chpldev_taskTable_set_active(taskID : chpl_taskID_t)
{
  chpldev_taskTable[taskID].state = taskState.active;
}

export proc chpldev_taskTable_set_suspended(taskID : chpl_taskID_t)
{
  chpldev_taskTable[taskID].state = taskState.suspended;
}

export proc chpldev_taskTable_get_tl_info(taskID : chpl_taskID_t)
{
  return chpldev_taskTable[taskID].tl_info;
}

export proc chpldev_taskTable_print()
{
  for taskID in chpldev_taskTableD {
    stderr.writeln("- ", chpldev_taskTable[taskID].filename,
                   ":",  chpldev_taskTable[taskID].lineno,
                   " is ", chpldev_taskTable[taskID].state);
  }
}

use ChapelBase;
use ChapelIO;
use ChapelArray;
use DefaultRectangular;
use DefaultAssociative;

/*
   This code keeps track of tasks, their state, and where they
   spawned from.

   The taks information is used to generate a task report (optionally
   displayed when the user Ctrl+C's out of the program).

   The type chpl_taskID_t is a primitve type defined in the include
   files for each tasking layer.

*/

enum taskState { pending, active, suspended };

//
// This represents a currently running task.  The state, lineno, and
// filename members should be obvious; tl_info is information belonging
// to the tasking layer.
//
// If we included the parent in this, the print method could topologically
// sort the tasks and indent to show the parent/child relationships, which
// might be very nice.
//
record chpldev_Task {
  var state     : taskState;
  var lineno    : uint(32);
  var filename  : string;
  var tl_info   : uint(64);
}

var chpldev_taskTableD : domain(chpl_taskID_t, parSafe=false);
var chpldev_taskTable : [chpldev_taskTableD] chpldev_Task;

pragma "export" proc chpldev_taskTable_add(taskID   : chpl_taskID_t,
                                          lineno   : uint(32),
                                          filename : string,
                                          tl_info  : uint(64))
{
  if(!chpldev_taskTableD.member(taskID)) {
    chpldev_taskTableD.add(taskID);
  }
  chpldev_taskTable[taskID] = new chpldev_Task(taskState.pending,
                                               lineno, filename, tl_info);
}

pragma "export" proc chpldev_taskTable_remove(taskID : chpl_taskID_t)
{
  chpldev_taskTableD.remove(taskID);
}

pragma "export" proc chpldev_taskTable_set_active(taskID : chpl_taskID_t)
{
  chpldev_taskTable[taskID].state = taskState.active;
}

pragma "export" proc chpldev_taskTable_set_suspended(taskID : chpl_taskID_t)
{
  chpldev_taskTable[taskID].state = taskState.suspended;
}

pragma "export" proc chpldev_taskTable_get_tl_info(taskID : chpl_taskID_t)
{
  return chpldev_taskTable[taskID].tl_info;
}

pragma "export" proc chpldev_taskTable_print()
{
  for taskID in chpldev_taskTableD {
    stderr.writeln("- ", chpldev_taskTable[taskID].filename,
                   ":",  chpldev_taskTable[taskID].lineno,
                   " is ", chpldev_taskTable[taskID].state);
  }
}