in MPI/Environment.cs [242:358]
public Environment(ref string[] args, Threading threading)
{
if (Finalized)
{
throw new ObjectDisposedException("Constructor called when object already finalized.");
}
if (!Initialized)
{
int requiredThreadLevel = 0;
int providedThreadLevel;
switch (threading)
{
case Threading.Single:
requiredThreadLevel = Unsafe.MPI_THREAD_SINGLE;
break;
case Threading.Funneled:
requiredThreadLevel = Unsafe.MPI_THREAD_FUNNELED;
break;
case Threading.Serialized:
requiredThreadLevel = Unsafe.MPI_THREAD_SERIALIZED;
break;
case Threading.Multiple:
requiredThreadLevel = Unsafe.MPI_THREAD_MULTIPLE;
break;
}
if (args == null)
{
unsafe
{
int argc = 0;
byte** argv = null;
Unsafe.MPI_Init_thread(ref argc, ref argv, requiredThreadLevel, out providedThreadLevel);
}
}
else
{
ASCIIEncoding ascii = new ASCIIEncoding();
unsafe
{
// Copy args into C-style argc/argv
int my_argc = args.Length;
byte** my_argv = stackalloc byte*[my_argc];
for (int argidx = 0; argidx < my_argc; ++argidx)
{
// Copy argument into a byte array (C-style characters)
char[] arg = args[argidx].ToCharArray();
fixed (char* argp = arg)
{
int length = ascii.GetByteCount(arg);
byte* c_arg = stackalloc byte[length];
if (length > 0)
{
ascii.GetBytes(argp, arg.Length, c_arg, length);
}
my_argv[argidx] = c_arg;
}
}
// Initialize MPI
int mpi_argc = my_argc;
byte** mpi_argv = my_argv;
Unsafe.MPI_Init_thread(ref mpi_argc, ref mpi_argv, requiredThreadLevel, out providedThreadLevel);
// \todo Copy c-style argc/argv back into args
if (mpi_argc != my_argc || mpi_argv != my_argv)
{
args = new string[mpi_argc];
for (int argidx = 0; argidx < args.Length; ++argidx)
{
// Find the end of the string
int byteCount = 0;
while (mpi_argv[argidx][byteCount] != 0)
++byteCount;
// Determine how many Unicode characters we need
int charCount = ascii.GetCharCount(mpi_argv[argidx], byteCount);
// Convert ASCII characters into unicode characters
char[] chars = new char[charCount];
fixed (char* argp = chars)
{
ascii.GetChars(mpi_argv[argidx], byteCount, argp, charCount);
}
// Create the resulting string
args[argidx] = new string(chars);
}
}
}
}
switch (providedThreadLevel)
{
case Unsafe.MPI_THREAD_SINGLE:
Environment.providedThreadLevel = Threading.Single;
break;
case Unsafe.MPI_THREAD_FUNNELED:
Environment.providedThreadLevel = Threading.Funneled;
break;
case Unsafe.MPI_THREAD_SERIALIZED:
Environment.providedThreadLevel = Threading.Serialized;
break;
case Unsafe.MPI_THREAD_MULTIPLE:
Environment.providedThreadLevel = Threading.Multiple;
break;
default:
throw new ApplicationException("MPI.NET: Underlying MPI library returned incorrect value for thread level");
}
// Setup communicators
Communicator.world = Intracommunicator.Adopt(Unsafe.MPI_COMM_WORLD);
Communicator.self = Intracommunicator.Adopt(Unsafe.MPI_COMM_SELF);
}
}