globalizer.cpp   [plain text]


/*
 * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved.
 * 
 * @APPLE_LICENSE_HEADER_START@
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this
 * file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 */


//
// globalizer - multiscope globalization services.
//
// This is a tentative, partial implementation.
// Status:
//	module scope: constructs, optional cleanup
//	thread scope: constructs, optional cleanup
//	process scope: not implemented (obsolete implementation, unused)
//	system scope: not implemented (probably never will)
//
// @@@ Assumption: {bool,T*} atomic unless PTHREAD_STRICT
//
#include <security_utilities/globalizer.h>
#include <security_utilities/debugging.h>
#include <cstdlib>
#include <stdexcept>

//
// The Error class thrown if Nexus operations fail
//
GlobalNexus::Error::~Error() throw()
{
}

void ModuleNexusCommon::do_create(void *(*make)())
{
    try
    {
        pointer = make();
    }
    catch (...)
    {
        pointer = NULL;
    }
}



void *ModuleNexusCommon::create(void *(*make)())
{
    dispatch_once(&once, ^{do_create(make);});
    
    if (pointer == NULL)
    {
        ModuleNexusError::throwMe();
    }
    
    return pointer;
}


//
// Process nexus operation
//
ProcessNexusBase::ProcessNexusBase(const char *identifier)
{
	const char *env = getenv(identifier);
	if (env == NULL) {	// perhaps we're first...
		auto_ptr<Store> store(new Store);
		char form[2*sizeof(Store *) + 2];
		sprintf(form, "*%p", &store);
		setenv(identifier, form, 0);	// do NOT overwrite...
		env = getenv(identifier);		// ... and refetch to resolve races
		if (sscanf(env, "*%p", &mStore) != 1)
			throw std::runtime_error("environment communication failed");
		if (mStore == store.get())		// we won the race...
			store.release();			// ... so keep the store
	} else
		if (sscanf(env, "*%p", &mStore) != 1)
			throw std::runtime_error("environment communication failed");
}