text:
"""Decorators that wrap a function.

If the function is defined in the file where you want to use the decorator,
you can decorate the function at define time:

.. code-block:: python

    @decorator
    def somefunc():
        return

If the function is defined somewhere else, do:

.. code-block:: python

    from numpy import mean

    mean = decorator(mean)
"""

from time import time, sleep
from os import makedirs, environ
import os.path
from os.path import join, dirname, getmtime

from .os import _is_cnspath, _no_trailing_slash, cp, rm

from .log import get_logger
logger = get_logger()

def colossus_interface(somefunc):
    """Wraps black-box functions to read from and write to Google Colossus.

    Because it's hard (if possible at all) to figure out which path is
    input, and which is output, when the input function is black-box, this is
    a "best-effort" decorator (see below for warnings).

    This decorator works by looping through all the positional and keyword
    parameters, copying CNS paths that exist prior to ``somefunc`` execuation
    to temporary local locations, running ``somefunc`` and writing its output
    to local locations, and finally copying local paths that get modified by
    ``somefunc`` to their corresponding CNS locations.

    Warning:
        Therefore, if ``somefunc``'s output already exists (e.g., you are
        re-running the function to overwrite the old result), it will be
        copied to local, overwritten by ``somefunc`` locally, and finally
        copied back to CNS. This doesn't lead to wrong behaviors, but is
        inefficient.

    This decorator doesn't depend on Blaze, as it's using the ``fileutil``
    CLI, rather than ``google3.pyglib.gfile``. This is convenient in at least
    two cases:

    - You are too lazy to use Blaze, want to run tests quickly on your local
      machine, but need access to CNS files.
    - Your IO is more complex than what ``with gfile.Open(...) as h:`` can do
      (e.g., a Blender function importing an object from a path), in which
      case you have to copy the CNS file to local ("local" here could also
      mean a Borglet's local).

    This interface generally works with resolved paths (e.g.,
    ``/path/to/file``), but not with wildcard paths (e.g., ``/path/to/???``),
    sicne it's hard (if possible at all) to guess what your function tries to
    do with such wildcard paths.

    Writes
        - Input files copied from Colossus to ``$TMP/``.
        - Output files generated to ``$TMP/``, to be copied to Colossus.
    """
    # $TMP set by Borg or yourself (e.g., with .bashrc)
    tmp_dir = environ.get('TMP', '/tmp/')

    def gen_local_path(cns_path):
        keep_last_n = 3
        cns_path = _no_trailing_slash(cns_path)
        local_basename = '_'.join(cns_path.split('/')[-keep_last_n:])
        # Prefixed by time to avoid dupes
        local_path = join(tmp_dir, '%f_%s' % (time(), local_basename))
        # local_path guaranteed to not end with '/'
        return local_path

    def cp_404ok(src, dst):
        try:
            cp(src, dst)
            logger.debug("\n%s\n\tcopied to\n%s", src, dst)
        except FileNotFoundError:
            logger.warning(("Source doesn't exist yet:\n\t%s\n"
                            "OK if this will be the output"), src)

    def wrapper(*arg, **kwargs):
        t_eps = 0.05 # seconds buffer for super fast somefunc
        # Fetch info. for all CNS paths
        arg_local, kwargs_local = [], {}
        cns2local = {}
        # Positional arguments
        for x in arg:
            if _is_cnspath(x):
                local_path = gen_local_path(x)
                cns2local[x] = local_path
                arg_local.append(local_path)
            else: # intact
                arg_local.append(x)
        # Keyword arguments
        for k, v in kwargs.items():
            if _is_cnspath(v):
                local_path = gen_local_path(v)
                cns2local[v] = local_path
                kwargs_local[k] = local_path
            else: # intact
                kwargs_local[k] = v
        # For reading: copy CNS paths that exist to local
        # TODO: what if some of those paths are not input? Copying them to
        # local is a waste (but harmless)
        for cns_path, local_path in cns2local.items():
            cp_404ok(cns_path, local_path)
        # Run the real function
        t0 = time()
        sleep(t_eps)
        results = somefunc(*arg_local, **kwargs_local)
        # For writing: copy local paths that are just modified and correspond
        # to CNS paths back to CNS
        for cns_path, local_path in cns2local.items():
            if os.path.exists(local_path) and getmtime(local_path) > t0:
                cp_404ok(local_path, cns_path)
        # Free up the space by deleting the temporary files
        for _, local_path in cns2local.items():
            rm(local_path)
        return results

    return wrapper

def timeit(somefunc):
    """Outputs the time a function takes to execute."""
    def wrapper(*arg, **kwargs):
        t0 = time()
        results = somefunc(*arg, **kwargs)
        t = time() - t0
        logger.info("Time elapsed: %f seconds", t)
        return results

    return wrapper

def existok(makedirs_func):
    """Implements the ``exist_ok`` flag in 3.2+, which avoids race conditions,
    where one parallel worker checks the folder doesn't exist and wants to
    create it with another worker doing so faster.
    """
    def wrapper(*args, **kwargs):
        try:
            makedirs_func(*args, **kwargs)
        except OSError as e:
            if e.errno != 17:
                raise
            logger.debug("%s already exists, but that is OK", args[0])

    return wrapper

def main():
    """Unit tests that can also serve as example usage."""
    # timeit
    @timeit
    def findsums(x, y, z):
        sleep(1)
        return x + y, x + z, y + z, x + y + z
    print(findsums(1, 2, 3))

    # existok
    newdir = join(dirname(__file__), 'test')
    makedirs_ = existok(makedirs)
    makedirs_(newdir)
    makedirs_(newdir)

if __name__ == '__main__':
    main()


text:
Q: ¿Cómo añadir un h2 centrado al comienzo de este section sin que me lo tome como un elemento inline? Básicamente lo que intento hacer es colocar este h2:
 Entrenamientos online intensivos, prácticos y de corta duración.
 como un título centrado al comienzo del section pero cuando lo coloco se posiciona a la izquierda o me rompe las cards de abajo y lo toma como columna en lugar de fila que es lo que quiero.
Les dejo el detalle de mi código html y css donde si bien no aparece el h2 quisiera saber dónde debería colocarlo.

 /*-----------------Cards cursos------------*/

.cardCursos{
background-image: url(../img/bckcursos.png);
background-attachment: fixed;
background-repeat: no-repeat;
background-size: cover;
background-position: 50%;
height: 100vh;
width: 100%;
}

.fnd{
background-color: #4489a8;
z-index: 0;
width: 100%;
position: absolute;
opacity: .75;
height: 100vh;
left: 0;
}

.cardForma{
height: 100vh;
padding: 0 4em;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
z-index: 10;
}

.undiv{
perspective: 1000px;
height: 28vh;
width: 100%;
cursor: pointer;
margin: 10px;
}

.cardFront{
transform-style: preserve-3d;
height: 100%;
width: 100%;
transition: 0.5s ease;
}

.front,.cardBack{
height: 100%;
width: 100%;
transform-style: preserve-3d;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
border-radius: 0.4em;
position: absolute;
top: 0;
bottom: 0;
backface-visibility: hidden;
}

.front{
background: #ffffff;
}

.front img{
width: 80px;
height: 80px;
}

.cardBack{
background-color: #2e2b3f;
transform: rotateX(180deg);
}

.front h3{
color: #2e2b3f;
font-size: 15px;
font-weight: 600;
letter-spacing: 0.04em;
}

.contentC{
transform: translateZ(60px);
}

.contentC h3{
margin-top: 1em;
}

.contentC p{
font-size: 14px;
line-height: 2em;
letter-spacing: 0.02em;
padding: 0 3em;
}

.undiv:hover .cardFront{
transform: rotateX(180deg);

}
/*-----------------Fin de Cursos------------*/

@media screen and (min-width: 992px) {
.cardCursos{
    padding: 0 1em;
}

.undiv{
    flex-basis: 0 0 25%;
    max-width: 25%;
    padding: 0 1em;
}

}

@media (max-width: 1440px){
.cardForma{
flex-wrap: nowrap;
}
}

100% remoto

Podés acceder a la plataforma desde tu compu o celular desde donde te
                                            encuentres.

Desarrollo de habilidades

Buscamos simular los espacios de trabajo lo más real posible.

Entrenamiento por cohorte

Grupos limitados con espacios de intercambio.

Comunidad de pares

Forma parte de una comunidad compuesta por mentores, profesionales y
                                            compañeros.

A: No se si esque antes quieres poner un h2 o si los h3 que tienes en los cards quieres centrarlos.
Igualmente te dejo una demo aqui, tanto en los h3 como implementando un h2

Holiii

100% remoto

Podés acceder a la plataforma desde tu compu o celular desde donde te
                                                encuentres.

Desarrollo de habilidades

Buscamos simular los espacios de trabajo lo más real posible.

Entrenamiento por cohorte

Grupos limitados con espacios de intercambio.

Comunidad de pares

Forma parte de una comunidad compuesta por mentores, profesionales y
                                                compañeros.

````

<!-- language: lang-css -->

 /*-----------------Cards cursos------------*/

.cardCursos{
    background-image: url(../img/bckcursos.png);
    background-attachment: fixed;
    background-repeat: no-repeat;
    background-size: cover;
    background-position: 50%;
    height: 100vh;
    width: 100%;
}

.fnd{
    background-color: #4489a8;
    z-index: 0;
    width: 100%;
    position: absolute;
    opacity: .75;
    height: 100vh;
    left: 0;
}

.cardForma{
    height: 100vh;
    padding: 0 4em;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-around;
    align-items: center;
    z-index: 10;
}

.undiv{
    perspective: 1000px;
    height: 28vh;
    width: 100%;
    cursor: pointer;
    margin: 10px;
}

.cardFront{
    transform-style: preserve-3d;
    height: 100%;
    width: 100%;
    transition: 0.5s ease;
}

.front,.cardBack{
    height: 100%;
    width: 100%;
    transform-style: preserve-3d;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    border-radius: 0.4em;
    position: absolute;
    top: 0;
    bottom: 0;
    backface-visibility: hidden;
}

.front{
    background: #ffffff;
}

.front img{
    width: 80px;
    height: 80px;
}

.cardBack{
    background-color: #2e2b3f;
    transform: rotateX(180deg);
}

.front h3{
    color: #2e2b3f;
    font-size: 15px;
    font-weight: 600;
    letter-spacing: 0.04em;
}

.contentC{
    transform: translateZ(60px);
}

.contentC h3{
    margin-top: 1em;
}

.contentC p{
    font-size: 14px;
    line-height: 2em;
    letter-spacing: 0.02em;
    padding: 0 3em;
}

.undiv:hover .cardFront{
    transform: rotateX(180deg);

}
/*-----------------Fin de Cursos------------*/

@media screen and (min-width: 992px) {
    .cardCursos{
        padding: 0 1em;
    }

    .undiv{
        flex-basis: 0 0 25%;
        max-width: 25%;
        padding: 0 1em;
    }

}

@media (max-width: 1440px){
.cardForma{
    flex-wrap: nowrap;
}
} ```

A: Solo necesitas poner el encabezado dentro de la sección, pero antes del contenedor flexible y crear la regla CSS para centrar:

/*-----------------Cards cursos------------*/

.cardCursos{
background-image: url(../img/bckcursos.png);
background-attachment: fixed;
background-repeat: no-repeat;
background-size: cover;
background-position: 50%;
height: 100vh;
width: 100%;
}

/* Configurar encabezado */
.cardCursos h2 {
    text-align: center;
}

.fnd{
background-color: #4489a8;
z-index: 0;
width: 100%;
position: absolute;
opacity: .75;
height: 100vh;
left: 0;
}

.cardForma{
height: 100vh;
padding: 0 4em;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
z-index: 10;
}

.undiv{
perspective: 1000px;
height: 28vh;
width: 100%;
cursor: pointer;
margin: 10px;
}

.cardFront{
transform-style: preserve-3d;
height: 100%;
width: 100%;
transition: 0.5s ease;
}

.front,.cardBack{
height: 100%;
width: 100%;
transform-style: preserve-3d;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
border-radius: 0.4em;
position: absolute;
top: 0;
bottom: 0;
backface-visibility: hidden;
}

.front{
background: #ffffff;
}

.front img{
width: 80px;
height: 80px;
}

.cardBack{
background-color: #2e2b3f;
transform: rotateX(180deg);
}

.front h3{
color: #2e2b3f;
font-size: 15px;
font-weight: 600;
letter-spacing: 0.04em;
}

.contentC{
transform: translateZ(60px);
}

.contentC h3{
margin-top: 1em;
}

.contentC p{
font-size: 14px;
line-height: 2em;
letter-spacing: 0.02em;
padding: 0 3em;
}

.undiv:hover .cardFront{
transform: rotateX(180deg);

}
/*-----------------Fin de Cursos------------*/

@media screen and (min-width: 992px) {
.cardCursos{
    padding: 0 1em;
}

.undiv{
    flex-basis: 0 0 25%;
    max-width: 25%;
    padding: 0 1em;
}

}

@media (max-width: 1440px){
.cardForma{
flex-wrap: nowrap;
}
}

Entrenamientos online intensivos, prácticos y de corta duración.

100% remoto

Podés acceder a la plataforma desde tu compu o celular desde donde te
                                            encuentres.

Desarrollo de habilidades

Buscamos simular los espacios de trabajo lo más real posible.

Entrenamiento por cohorte

Grupos limitados con espacios de intercambio.

Comunidad de pares

Forma parte de una comunidad compuesta por mentores, profesionales y
                                            compañeros.

redpajama_set_name: RedPajamaStackExchange


text:
Prospects of technocratic government in Ukraine (Part 1)
Author : Serhiy Zvihlyanych
This principle has never been implemented in the ideal form in the particular state
europarl.europa.eu
In Ukraine, Natalia Yaresko and Aivaras Abromavicius are called technocrats
Ukrainian political lexicon was enriched by a new word - "technocrats". Now it is used not less than the notorious "reform." About technocrats we talk on the sidelines of Parliament, on television, and even on the streets. But there is a reason to believe that, as often happens, "heard a bell, but do not know where it is," or, in other words, heard a new buzzword, but in fact has not yet figured out its meaning. Do not worry, we will help you.
The origins of the theory
What is technocracy? This is a Greek word τεχνοκρατία, consisting of two components - τέχνη, "skill", and κράτος, "power." That is the power of the masters. Scientifically, the term can be defined as the principle of building a society in which power belongs to the scientific and technical experts. Technocracy is very close to the meritocracy, according to which leadership positions should take the most capable people, regardless of their social background and financial prosperity. Both concepts involve the establishment of free competition, to the gifted, talented people had a chance to take a high social position. Such a model of social justice.
Related: Groisman and Yaresko might replace current PM Yatsenyuk
The philosophical and political thought technocratic tradition has a long history. Clearly, the idea of a modern society, knowledge-managed carriers, was first mentioned by Plato. In his work "The State" he defends the thesis that the state must be managed by the carriers of knowledge - class of philosophers. In the XVII century the idea of the use of scientific knowledge for the management of society was developed in the writings of Francis Bacon and Tommaso Campanella. However, all this was just a hint of technocratic ideas, which appeared only at a certain stage of social development. The first holistic concept of the impact of science, industry and technical experts on the socio-political development was created by Henri Saint-Simon. In the works of Saint-Simon there are two major components of all later technocratic concepts: community management on scientific principles and the leading political role of the scientific and technical experts. Saint-Simon was rightly called the forerunner of technocracy and the first of its ideologist.
To speak of technocracy, first of all a fairly numerous layers of scientific and technical experts was needed. And it was only in the second half of the XIX century, with the industrial revolution in the advanced countries, the mass use of machines in production, and then in other areas. Initially technocracy was a response to the challenge facing the engineers from the beginning of the XX century, when under the leadership of developing capitalism plants often in pursuit of profit hindered scientific progress.
mdlsestosg.it
Technocracy in politics
However, in the 1920s, the rapid development of science and technology, greatly improving production, changed the social fabric. Technical progress was inextricably linked with the use and implementation of scientific and technological developments in the life of mankind. It is clear that this process did not go unnoticed by philosophers of the time. The main provision of the technocratic concept of a society was technological determinism. It assumed a critical role of engineering and technology in the development of socio-economic structures. In the works of Veblen, this was the implementation of the doctrine according to which the decisive role belonged not only in economic development, but also decision-making policy should belong to the art. Thorstein Veblen described his views in a social utopia "The Engineers and the Price System" (1921) and other works. In 1941, American sociologist Bernheim in his book "The Managerial Revolution," referring to the "government of experts", put forward the idea that the technocracy in the face of political management has become a reality in a number of countries and that under the influence of "technological revolution" capitalism gave way not to socialism, but "managerial society".
Related: Contender for PM's post: Natalia Yaresko
Technocratic social order is characterized by the fact that the income of production and distribution process is under the control of society and delegated to the most qualified specialists. Economy of the technocratic society has a non-market character. The social structure of a society is not based on property relations, but on the knowledge and qualifications.
On this basis, the idea of a technocratic government is the government experts that effectively perform the administrative tasks. The technocratic system, in which the economy is governed by economists, social policy is governed by political scientists, the health system is operated by medical professionals, other sectors - relevant specialists, who work and share knowledge together, coordinated by specialists-managers, the performance of each is maximized as much as possible.
Technocracy can also use the control system, in which the laws are enforced by designing systems so that they cannot be broken. For example, to prevent people from traveling by tram without paying for travel, car doors can be designed in such a way that the payment was needed to open the door. The same idea can be applied on a much larger scale, with automated social supervision, intelligent systems that automatically control or restrict the activities of people in order to prevent illegal activities.
This principle has never been implemented in the ideal form at the level of the particular state.
Related: Natalia Yaresko has a small chance to lead the Cabinet of Ministers, - source
Related: Yaresko can replace Yatsenyuk on the post of Prime Minister this week
Ukraine Kyiv Abromavicius Yaresko Ukrainian politics Ukrainian politicians technocracy Carlo Ciampi technocrats
POLITICS14:48President Trump's farewell address
POLITICS14:43Five facts about US new first lady Jill Biden
POLITICS14:18Biden inauguration: Democrat to be sworn in as Trump leaves office
UKRAINE TOP 13:42Swedish company might test its drug for Covid-19 therapy in Ukraine
SOCIETY09:38Unfair world race for Covid-19 vaccine
POLITICS22:55What is known for Crown Agents, through which Ukraine will purchase vaccine against Сovid-19?
POLITICS21:47Banks survive, fast credit market drowning: How Ukrainians take loans during pandemic
POLITICS13:41Service sector switches to Ukrainian language: Exceptions and threats
POLITICS12:08Germany's new Chancellor: Armin Laschet to become Angela Merkel's successor?

redpajama_set_name: RedPajamaCommonCrawl


text:
Q: Can't install new linux kernel even after squeeze-backports I'm trying to upgrade my kernel version from 2.6.32 to 3.2.0.0. When I try:
sudo apt-get install linux-image-3.16.0-4-amd64

I get the following error message:
 linux-image-3.16.0-4-amd64 : Depends: linux-base (>= 3~) but 2.6.32-48squeeze6 is to be installed
                              Recommends: firmware-linux-free (>= 3~) but it is not going to be installed
                              Recommends: irqbalance but it is not going to be installed
                              Breaks: initramfs-tools (< 0.110~) but 0.98.8 is to be installed

I read that the problem has to do with having two kernel versions at once, so I tried the squeeze backports option. After adding the line:
deb http://backports.debian.org/debian-backports squeeze-backports main contrib non-free

to my /etc/apt/sources.list, and running the following command:
sudo apt-get install -t squeeze-backports linux-image-3.16.0-4-amd64

I get the same error message as above. Can someone explain to me what the problem is, and how I would proceed to install the new kernel?
By the way, when I type in sudo apt-get install -f, I have the following message:
sudo apt-get -f install
Reading package lists... Done
Building dependency tree
Reading state information... Done
Correcting dependencies... failed.
The following packages have unmet dependencies:
    libfuzzy-dev : Depends: libfuzzy2 (= 2.12-1) but it is not installed
E: Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages.
E: Unable to correct dependencies


I am so excited, y'all! This little blog o' mine was nominated for the Liebster Award by Ya Gotta Have a Hobby and Bear & Lion. I am so incredibly grateful and honored!
// My hair's native land is Norway.
// I love words, and think more about proper spelling & grammar than one girl should.
// Dislike football and basketball. Love, however, volleyball, swimming, hockey, and snow/water sports.
// My mother died when I was just a girl. In fact, I wrote a blog post not that long ago, called Motherless Daughters.
// I can often be found wandering junk shops, thrift stores, antique warehouses near and far.
// I've never broken a bone. I've sprained an ankle and fractured my nose, but have never had a full fledge brake.
// I have 3 tattoos.
// I wish I had zero tattoos.
// I had skin cancer 1.5 years ago. I went into the dermatologist to have her examine a mole on my back, and left the office instead with a chunk of flesh taken out of my nose. They called 2 days later and told me I had skin cancer. Quite frankly, one of the worst phone calls I've ever received. Read my story HERE.
// I love to puzzle. 5000 pieces is the biggest I've laid. Did it with a friend.
// I'm a music geek. My husband likes to quiz me about various songs we might hear in public. 9 out of 10 times, I know the band behind the song and am able to provide a bit of trivia about them.
// There are 2 versions of myself: the 1) well-dressed, all-business corporate assistant during the week and the 2) boho/surfer-style, care-free spirit on the weekends.
// I could eat Asian food every day, for the rest of my life.
// When I was 6, I stole a piece of green bubble gum from the 7-Eleven. And the clerk totally saw me.
// I really admire my husband. He is full of integrity, he's humble, talented, smart and hard-working. And he's funny. And handsome.
What would you do if you won the lottery? Tithe some of it. Take a little trip to Italy (some time before I die). I have 3 kids to put through college, thus far, so I'm certain that in itself will eat up the majority.
How many pairs of shoes do you own? If I have to guess, I'm going to say 17-20. Half of them worn once.
What was your most cherished childhood possession? A blanket, otherwise known as "woobie." It was framed in a satin/silk trim that I would rub along the bottom of my nose when in a relaxed state.
Which is your favorite holiday and why? Christmas has always been my favorite holiday. Not just my favorite holiday, mind you, but my favorite time of year, period. It's due to the obvious: presents, although I do love giving gifts. There's just something about the season, the time of year, and the celebration of our Savior that makes Christmas my all-time favorite.
What is the last thing you went shopping for? Vick's Vapor Rub for babies, but ended up purchasing Maty's All Natural product instead. It doesn't have menthol, which I assume is better for little ones.
What is your favorite book? "When a woman has a kingdom heart, she has an active understanding of what matters most to the heart of God. She lives in the balance of passion and contentment. She learns to love well, give without regard to self, and forgive without hesitation. The woman with a kingdom heart may have a duffel bag full of possessions or enough treasures to fill a mansion, but she has learned to hold them with an open hand. Hold everything with open hands. I don't think we are ever allowed to grab hold of anything or anyone as though they matter more than the kingdom of heaven. When you hold relationships with open hands, then people come in and out of your life as gifts of grace to be cherished and enjoyed, not objects to be owned and manipulated. And then when you hold your dreams with open hands, you get to watch God resurrect what seemed dead and multiply what seemed small."- from my FAVORITE book A Beautiful Offering.
If you could have any superpower, what would it be? I picked super speed because i am always on the go and I never seem to have time to get it all done. So if I had super speed I could get everything done and then sit back and enjoy what is left of my day.
If you could have dinner with any fictional character, who would it be? Sherlock Holmes. Brilliant mind!
Name three things you MUST do in your lifetime. A) See each of my kids grow up to be happy adults, and meet their spouse and child(ren). B) Travel all over Italy. C) Make my husband proud to have married me.
3. What was your most cherished childhood possession?
5. Do you prefer sunrises or sunsets?
6. Which is your favorite holiday and why?
7. What is the last thing you went shopping for?
9. If you could have any superpower, what would it be?
10. If you could have dinner with any fictional character, who would it be?
11. Name three things you MUST do in your lifetime.
You're so very welcome. And deserving!
I realize it takes time. I think it took me 1.5 weeks before I finally reciprocated.
haha love this, I say toilet paper under!! sorry ;)!
Congrats, Mandi! I really enjoyed reading this post and getting to know you better! I especially love your answer to number 11!
Aw, you're incredibly sweet, Cindy -- thank you!
You are beautiful. I am loving your blog. Like..absolutely loving it. I love reading more about people, and I'm a music freak too! Look at that! haha.
Andrea! I love to see your name come across my blog or Twitter -- I just adore you. Thanks for the congrats, and most certainly grab that book!
Yay -- Congrats to you!
Thank you, Christine -- I appreciate you so very much!
So not happy to read that you also had skin cancer. :( It was not a fun experience for me, either.
I love, love, love Asian food, too. It's my favorite!


Artist Bill Miller was a founding member of Industrial Arts Co-Op in Pittsburgh, a group that created large-scale sculptures made of discarded materials found at abandoned industrial sites. The goal of the installations was to bring attention to the damaging impact of industrialization.
While constructing the sculptures, Miller came across an unusual art material: vintage linoleum scraps. He has been creating linoleum masterpieces for over 20 years. His collage-like linoleum paintings are made using only recycled and vintage flooring, no extra paint is added.
Miller's artwork has been exhibited in several museums and galleries. To view more of his work, please visit his website at billmillerart.com.


Beautiful weather is coming up in the next few days in Los Angeles, just in time for the New Year. This is a good time to make a quick check around your basement and find out if there is a need to reapply waterproofing materials that have worn out.
Check for peeling wallpaper or paint on the walls, musty odors in rarely-used rooms such as basements and attics, and unnatural increase in your water bill. These are some of the signs that there could be water leakage in your home.
Don't have the time do the checking? Westside Company can do this for you. Call us at 310 994 4626 or e-mail us at westsidewaterproofing@gmail.com for more information.


text:
Dorothy Jane McGarvey, 91
MUNCIE - Dorothy Jane McGarvey, 91, passed away on Tuesday, November 18, 2014 at her daughter's residence.
Jane (as she was known), was born to James C. and Mary P. (Davis-Graham) Haley on March 9, 1923 in Muncie.
She had retired from the Muncie Aviation Corporation after several years of service.
Jane loved sewing, knitting, and crafting.
She is survived by her daughter, Barbara Jo (companion, Tyrone Pritchett) Jackson; step-daughters, Shirley Smith and Elizabeth Petersen; brother, John E. (Patricia) Graham; sister-in-law, Marjorie Graham; nieces and nephews, Randie (Steve) Long, Joanne (Scott) Currie, Todd Graham, David Graham, Dianna Graham Hall, Thalia Messer, Patty Roetzel, Peggy Swails, Teela McKenzie, and several great-nieces and nephews; several step-grandchildren and step-great-grandchildren and special grand-dogs, Paisley and Pugsley also survive.
Jane is preceded in death by her parents; husband, Lawrence D. McGarvey; step-father, Blake Haley; brothers, Joseph and James Graham.
The family would like to extend a special Thank You to special friends, Kristine Coatie, Emily Miller, and Barbara Richards.
Cremation will take place and there will be no public services.
Memorial contributions may be made to Gentiva Hospice, 6431 South East Street, Indianapolis, Indiana 46227 or Elmcroft Senior Living Heartland Village, 1601 North Morrison, Muncie, IN 47304.
Arrangements have been entrusted to Elm Ridge Funeral Home and Memorial Park.


Among the AS-600, the AS-900 and the AS-1500, the AS-470 is the smallest version of our mobile PA-series. The difference to its bigger brothers is made by the tweeter. Whereas the other active-systems are fitted with horns, the 470 is equipped with a dome tweeter. A dome tweeter stands for a clean an fine sound, but is restricted in the high end area. According to that, presentations or the like are the perfect occasions for the 470. The other advantages of the series, a simple and fast installation and an ambitious performance in spite of its size, do remain, of course.
Perfectly tuned system for demanding home users, DJ home recording, party etc.


K-1 visa preparation support to help prepare your Ethiopian I-129F petition for your Ethiopian Fiancee to USA. K-3 spouse visa I-130 and USCIS Green Card Adjustment of Status.
Ethiopian K-1 visa preparation support to help prepare your I-129F petition for your Ethiopian Fiancee to USA. K-3 spouse visa I-130 and USCIS Green Card Adjustment of Status.


Once again, this year Summit will be held at ExCeL London.
There is a wide range of hotels in the area, some located within walking distance of ExCeL, others easily accessible by public transport or taxi.
To view the full list of hotels and to book your room at negotiated rates click on the link below. Register early, as rooms will fill up quickly.
To plan your journey to ExCeL London. Please note that this year Adobe Summit will take place at the West Entrance to ExCeL. You should alight the DLR at Custom House.
For more visitor information on ExCeL London visit the FAQ page.
and get even more out of Summit.


text:
export interface AlarmData {
    type: string,
    msg: string
}

export function isAlarmData(arg: any) : arg is AlarmData {
    return arg.type !== undefined && arg.type == "alarm";
}

redpajama_set_name: RedPajamaGithub


text:
namespace __sanitizer {

// SizeClassMap maps allocation sizes into size classes and back.
// Class 0 corresponds to size 0.
// Classes 1 - 16 correspond to sizes 16 to 256 (size = class_id * 16).
// Next 4 classes: 256 + i * 64  (i = 1 to 4).
// Next 4 classes: 512 + i * 128 (i = 1 to 4).
// ...
// Next 4 classes: 2^k + i * 2^(k-2) (i = 1 to 4).
// Last class corresponds to kMaxSize = 1 << kMaxSizeLog.
//
// This structure of the size class map gives us:
//   - Efficient table-free class-to-size and size-to-class functions.
//   - Difference between two consequent size classes is betweed 14% and 25%
//
// This class also gives a hint to a thread-caching allocator about the amount
// of chunks that need to be cached per-thread:
//  - kMaxNumCached is the maximal number of chunks per size class.
//  - (1 << kMaxBytesCachedLog) is the maximal number of bytes per size class.
//
// Part of output of SizeClassMap::Print():
// c00 => s: 0 diff: +0 00% l 0 cached: 0 0; id 0
// c01 => s: 16 diff: +16 00% l 4 cached: 256 4096; id 1
// c02 => s: 32 diff: +16 100% l 5 cached: 256 8192; id 2
// c03 => s: 48 diff: +16 50% l 5 cached: 256 12288; id 3
// c04 => s: 64 diff: +16 33% l 6 cached: 256 16384; id 4
// c05 => s: 80 diff: +16 25% l 6 cached: 256 20480; id 5
// c06 => s: 96 diff: +16 20% l 6 cached: 256 24576; id 6
// c07 => s: 112 diff: +16 16% l 6 cached: 256 28672; id 7
//
// c08 => s: 128 diff: +16 14% l 7 cached: 256 32768; id 8
// c09 => s: 144 diff: +16 12% l 7 cached: 256 36864; id 9
// c10 => s: 160 diff: +16 11% l 7 cached: 256 40960; id 10
// c11 => s: 176 diff: +16 10% l 7 cached: 256 45056; id 11
// c12 => s: 192 diff: +16 09% l 7 cached: 256 49152; id 12
// c13 => s: 208 diff: +16 08% l 7 cached: 256 53248; id 13
// c14 => s: 224 diff: +16 07% l 7 cached: 256 57344; id 14
// c15 => s: 240 diff: +16 07% l 7 cached: 256 61440; id 15
//
// c16 => s: 256 diff: +16 06% l 8 cached: 256 65536; id 16
// c17 => s: 320 diff: +64 25% l 8 cached: 204 65280; id 17
// c18 => s: 384 diff: +64 20% l 8 cached: 170 65280; id 18
// c19 => s: 448 diff: +64 16% l 8 cached: 146 65408; id 19
//
// c20 => s: 512 diff: +64 14% l 9 cached: 128 65536; id 20
// c21 => s: 640 diff: +128 25% l 9 cached: 102 65280; id 21
// c22 => s: 768 diff: +128 20% l 9 cached: 85 65280; id 22
// c23 => s: 896 diff: +128 16% l 9 cached: 73 65408; id 23
//
// c24 => s: 1024 diff: +128 14% l 10 cached: 64 65536; id 24
// c25 => s: 1280 diff: +256 25% l 10 cached: 51 65280; id 25
// c26 => s: 1536 diff: +256 20% l 10 cached: 42 64512; id 26
// c27 => s: 1792 diff: +256 16% l 10 cached: 36 64512; id 27
//
// ...
//
// c48 => s: 65536 diff: +8192 14% l 16 cached: 1 65536; id 48
// c49 => s: 81920 diff: +16384 25% l 16 cached: 1 81920; id 49
// c50 => s: 98304 diff: +16384 20% l 16 cached: 1 98304; id 50
// c51 => s: 114688 diff: +16384 16% l 16 cached: 1 114688; id 51
//
// c52 => s: 131072 diff: +16384 14% l 17 cached: 1 131072; id 52

template <uptr kMaxSizeLog, uptr kMaxNumCachedT, uptr kMaxBytesCachedLog>
class SizeClassMap {
  static const uptr kMinSizeLog = 4;
  static const uptr kMidSizeLog = kMinSizeLog + 4;
  static const uptr kMinSize = 1 << kMinSizeLog;
  static const uptr kMidSize = 1 << kMidSizeLog;
  static const uptr kMidClass = kMidSize / kMinSize;
  static const uptr S = 2;
  static const uptr M = (1 << S) - 1;

 public:
  static const uptr kMaxNumCached = kMaxNumCachedT;
  // We transfer chunks between central and thread-local free lists in batches.
  // For small size classes we allocate batches separately.
  // For large size classes we use one of the chunks to store the batch.
  struct TransferBatch {
    TransferBatch *next;
    uptr count;
    void *batch[kMaxNumCached];
  };

  static const uptr kMaxSize = 1UL << kMaxSizeLog;
  static const uptr kNumClasses =
      kMidClass + ((kMaxSizeLog - kMidSizeLog) << S) + 1;
  COMPILER_CHECK(kNumClasses >= 32 && kNumClasses <= 256);
  static const uptr kNumClassesRounded =
      kNumClasses == 32  ? 32 :
      kNumClasses <= 64  ? 64 :
      kNumClasses <= 128 ? 128 : 256;

  static uptr Size(uptr class_id) {
    if (class_id <= kMidClass)
      return kMinSize * class_id;
    class_id -= kMidClass;
    uptr t = kMidSize << (class_id >> S);
    return t + (t >> S) * (class_id & M);
  }

  static uptr ClassID(uptr size) {
    if (size <= kMidSize)
      return (size + kMinSize - 1) >> kMinSizeLog;
    if (size > kMaxSize) return 0;
    uptr l = MostSignificantSetBitIndex(size);
    uptr hbits = (size >> (l - S)) & M;
    uptr lbits = size & ((1 << (l - S)) - 1);
    uptr l1 = l - kMidSizeLog;
    return kMidClass + (l1 << S) + hbits + (lbits > 0);
  }

  static uptr MaxCached(uptr class_id) {
    if (class_id == 0) return 0;
    uptr n = (1UL << kMaxBytesCachedLog) / Size(class_id);
    return Max<uptr>(1, Min(kMaxNumCached, n));
  }

  static void Print() {
    uptr prev_s = 0;
    uptr total_cached = 0;
    for (uptr i = 0; i < kNumClasses; i++) {
      uptr s = Size(i);
      if (s >= kMidSize / 2 && (s & (s - 1)) == 0)
        Printf("\n");
      uptr d = s - prev_s;
      uptr p = prev_s ? (d * 100 / prev_s) : 0;
      uptr l = s ? MostSignificantSetBitIndex(s) : 0;
      uptr cached = MaxCached(i) * s;
      Printf("c%02zd => s: %zd diff: +%zd %02zd%% l %zd "
             "cached: %zd %zd; id %zd\n",
             i, Size(i), d, p, l, MaxCached(i), cached, ClassID(s));
      total_cached += cached;
      prev_s = s;
    }
    Printf("Total cached: %zd\n", total_cached);
  }

  static bool SizeClassRequiresSeparateTransferBatch(uptr class_id) {
    return Size(class_id) < sizeof(TransferBatch) -
        sizeof(uptr) * (kMaxNumCached - MaxCached(class_id));
  }

  static void Validate() {
    for (uptr c = 1; c < kNumClasses; c++) {
      // Printf("Validate: c%zd\n", c);
      uptr s = Size(c);
      CHECK_NE(s, 0U);
      CHECK_EQ(ClassID(s), c);
      if (c != kNumClasses - 1)
        CHECK_EQ(ClassID(s + 1), c + 1);
      CHECK_EQ(ClassID(s - 1), c);
      if (c)
        CHECK_GT(Size(c), Size(c-1));
    }
    CHECK_EQ(ClassID(kMaxSize + 1), 0);

    for (uptr s = 1; s <= kMaxSize; s++) {
      uptr c = ClassID(s);
      // Printf("s%zd => c%zd\n", s, c);
      CHECK_LT(c, kNumClasses);
      CHECK_GE(Size(c), s);
      if (c > 0)
        CHECK_LT(Size(c-1), s);
    }
  }
};

typedef SizeClassMap<17, 128, 16> DefaultSizeClassMap;
typedef SizeClassMap<17, 64,  14> CompactSizeClassMap;
template<class SizeClassAllocator> struct SizeClassAllocatorLocalCache;

// Memory allocator statistics
enum AllocatorStat {
  AllocatorStatMalloced,
  AllocatorStatFreed,
  AllocatorStatMmapped,
  AllocatorStatUnmapped,
  AllocatorStatCount
};

typedef u64 AllocatorStatCounters[AllocatorStatCount];

// Per-thread stats, live in per-thread cache.
class AllocatorStats {
 public:
  void Init() {
    internal_memset(this, 0, sizeof(*this));
  }

  void Add(AllocatorStat i, u64 v) {
    v += atomic_load(&stats_[i], memory_order_relaxed);
    atomic_store(&stats_[i], v, memory_order_relaxed);
  }

  void Set(AllocatorStat i, u64 v) {
    atomic_store(&stats_[i], v, memory_order_relaxed);
  }

  u64 Get(AllocatorStat i) const {
    return atomic_load(&stats_[i], memory_order_relaxed);
  }

 private:
  friend class AllocatorGlobalStats;
  AllocatorStats *next_;
  AllocatorStats *prev_;
  atomic_uint64_t stats_[AllocatorStatCount];
};

// Global stats, used for aggregation and querying.
class AllocatorGlobalStats : public AllocatorStats {
 public:
  void Init() {
    internal_memset(this, 0, sizeof(*this));
    next_ = this;
    prev_ = this;
  }

  void Register(AllocatorStats *s) {
    SpinMutexLock l(&mu_);
    s->next_ = next_;
    s->prev_ = this;
    next_->prev_ = s;
    next_ = s;
  }

  void Unregister(AllocatorStats *s) {
    SpinMutexLock l(&mu_);
    s->prev_->next_ = s->next_;
    s->next_->prev_ = s->prev_;
    for (int i = 0; i < AllocatorStatCount; i++)
      Add(AllocatorStat(i), s->Get(AllocatorStat(i)));
  }

  void Get(AllocatorStatCounters s) const {
    internal_memset(s, 0, AllocatorStatCount * sizeof(u64));
    SpinMutexLock l(&mu_);
    const AllocatorStats *stats = this;
    for (;;) {
      for (int i = 0; i < AllocatorStatCount; i++)
        s[i] += stats->Get(AllocatorStat(i));
      stats = stats->next_;
      if (stats == this)
        break;
    }
  }

 private:
  mutable SpinMutex mu_;
};

// Allocators call these callbacks on mmap/munmap.
struct NoOpMapUnmapCallback {
  void OnMap(uptr p, uptr size) const { }
  void OnUnmap(uptr p, uptr size) const { }
};

// Callback type for iterating over chunks.
typedef void (*ForEachChunkCallback)(uptr chunk, void *arg);

// SizeClassAllocator64 -- allocator for 64-bit address space.
//
// Space: a portion of address space of kSpaceSize bytes starting at
// a fixed address (kSpaceBeg). Both constants are powers of two and
// kSpaceBeg is kSpaceSize-aligned.
// At the beginning the entire space is mprotect-ed, then small parts of it
// are mapped on demand.
//
// Region: a part of Space dedicated to a single size class.
// There are kNumClasses Regions of equal size.
//
// UserChunk: a piece of memory returned to user.
// MetaChunk: kMetadataSize bytes of metadata associated with a UserChunk.
//
// A Region looks like this:
// UserChunk1 ... UserChunkN <gap> MetaChunkN ... MetaChunk1
template <const uptr kSpaceBeg, const uptr kSpaceSize,
          const uptr kMetadataSize, class SizeClassMap,
          class MapUnmapCallback = NoOpMapUnmapCallback>
class SizeClassAllocator64 {
 public:
  typedef typename SizeClassMap::TransferBatch Batch;
  typedef SizeClassAllocator64<kSpaceBeg, kSpaceSize, kMetadataSize,
      SizeClassMap, MapUnmapCallback> ThisT;
  typedef SizeClassAllocatorLocalCache<ThisT> AllocatorCache;

  void Init() {
    CHECK_EQ(kSpaceBeg,
             reinterpret_cast<uptr>(Mprotect(kSpaceBeg, kSpaceSize)));
    MapWithCallback(kSpaceEnd, AdditionalSize());
  }

  void MapWithCallback(uptr beg, uptr size) {
    CHECK_EQ(beg, reinterpret_cast<uptr>(MmapFixedOrDie(beg, size)));
    MapUnmapCallback().OnMap(beg, size);
  }

  void UnmapWithCallback(uptr beg, uptr size) {
    MapUnmapCallback().OnUnmap(beg, size);
    UnmapOrDie(reinterpret_cast<void *>(beg), size);
  }

  static bool CanAllocate(uptr size, uptr alignment) {
    return size <= SizeClassMap::kMaxSize &&
      alignment <= SizeClassMap::kMaxSize;
  }

  NOINLINE Batch* AllocateBatch(AllocatorStats *stat, AllocatorCache *c,
                                uptr class_id) {
    CHECK_LT(class_id, kNumClasses);
    RegionInfo *region = GetRegionInfo(class_id);
    Batch *b = region->free_list.Pop();
    if (b == 0)
      b = PopulateFreeList(stat, c, class_id, region);
    region->n_allocated += b->count;
    return b;
  }

  NOINLINE void DeallocateBatch(AllocatorStats *stat, uptr class_id, Batch *b) {
    RegionInfo *region = GetRegionInfo(class_id);
    CHECK_GT(b->count, 0);
    region->free_list.Push(b);
    region->n_freed += b->count;
  }

  static bool PointerIsMine(const void *p) {
    return reinterpret_cast<uptr>(p) / kSpaceSize == kSpaceBeg / kSpaceSize;
  }

  static uptr GetSizeClass(const void *p) {
    return (reinterpret_cast<uptr>(p) / kRegionSize) % kNumClassesRounded;
  }

  void *GetBlockBegin(const void *p) {
    uptr class_id = GetSizeClass(p);
    uptr size = SizeClassMap::Size(class_id);
    if (!size) return 0;
    uptr chunk_idx = GetChunkIdx((uptr)p, size);
    uptr reg_beg = (uptr)p & ~(kRegionSize - 1);
    uptr beg = chunk_idx * size;
    uptr next_beg = beg + size;
    if (class_id >= kNumClasses) return 0;
    RegionInfo *region = GetRegionInfo(class_id);
    if (region->mapped_user >= next_beg)
      return reinterpret_cast<void*>(reg_beg + beg);
    return 0;
  }

  static uptr GetActuallyAllocatedSize(void *p) {
    CHECK(PointerIsMine(p));
    return SizeClassMap::Size(GetSizeClass(p));
  }

  uptr ClassID(uptr size) { return SizeClassMap::ClassID(size); }

  void *GetMetaData(const void *p) {
    uptr class_id = GetSizeClass(p);
    uptr size = SizeClassMap::Size(class_id);
    uptr chunk_idx = GetChunkIdx(reinterpret_cast<uptr>(p), size);
    return reinterpret_cast<void*>(kSpaceBeg + (kRegionSize * (class_id + 1)) -
                                   (1 + chunk_idx) * kMetadataSize);
  }

  uptr TotalMemoryUsed() {
    uptr res = 0;
    for (uptr i = 0; i < kNumClasses; i++)
      res += GetRegionInfo(i)->allocated_user;
    return res;
  }

  // Test-only.
  void TestOnlyUnmap() {
    UnmapWithCallback(kSpaceBeg, kSpaceSize + AdditionalSize());
  }

  void PrintStats() {
    uptr total_mapped = 0;
    uptr n_allocated = 0;
    uptr n_freed = 0;
    for (uptr class_id = 1; class_id < kNumClasses; class_id++) {
      RegionInfo *region = GetRegionInfo(class_id);
      total_mapped += region->mapped_user;
      n_allocated += region->n_allocated;
      n_freed += region->n_freed;
    }
    Printf("Stats: SizeClassAllocator64: %zdM mapped in %zd allocations; "
           "remains %zd\n",
           total_mapped >> 20, n_allocated, n_allocated - n_freed);
    for (uptr class_id = 1; class_id < kNumClasses; class_id++) {
      RegionInfo *region = GetRegionInfo(class_id);
      if (region->mapped_user == 0) continue;
      Printf("  %02zd (%zd): total: %zd K allocs: %zd remains: %zd\n",
             class_id,
             SizeClassMap::Size(class_id),
             region->mapped_user >> 10,
             region->n_allocated,
             region->n_allocated - region->n_freed);
    }
  }

  // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
  // introspection API.
  void ForceLock() {
    for (uptr i = 0; i < kNumClasses; i++) {
      GetRegionInfo(i)->mutex.Lock();
    }
  }

  void ForceUnlock() {
    for (int i = (int)kNumClasses - 1; i >= 0; i--) {
      GetRegionInfo(i)->mutex.Unlock();
    }
  }

  // Iterate over all existing chunks.
  // The allocator must be locked when calling this function.
  void ForEachChunk(ForEachChunkCallback callback, void *arg) {
    for (uptr class_id = 1; class_id < kNumClasses; class_id++) {
      RegionInfo *region = GetRegionInfo(class_id);
      uptr chunk_size = SizeClassMap::Size(class_id);
      uptr region_beg = kSpaceBeg + class_id * kRegionSize;
      for (uptr chunk = region_beg;
           chunk < region_beg + region->allocated_user;
           chunk += chunk_size) {
        // Too slow: CHECK_EQ((void *)chunk, GetBlockBegin((void *)chunk));
        callback(chunk, arg);
      }
    }
  }

  typedef SizeClassMap SizeClassMapT;
  static const uptr kNumClasses = SizeClassMap::kNumClasses;
  static const uptr kNumClassesRounded = SizeClassMap::kNumClassesRounded;

 private:
  static const uptr kRegionSize = kSpaceSize / kNumClassesRounded;
  static const uptr kSpaceEnd = kSpaceBeg + kSpaceSize;
  COMPILER_CHECK(kSpaceBeg % kSpaceSize == 0);
  // kRegionSize must be >= 2^32.
  COMPILER_CHECK((kRegionSize) >= (1ULL << (SANITIZER_WORDSIZE / 2)));
  // Populate the free list with at most this number of bytes at once
  // or with one element if its size is greater.
  static const uptr kPopulateSize = 1 << 14;
  // Call mmap for user memory with at least this size.
  static const uptr kUserMapSize = 1 << 16;
  // Call mmap for metadata memory with at least this size.
  static const uptr kMetaMapSize = 1 << 16;

  struct RegionInfo {
    BlockingMutex mutex;
    LFStack<Batch> free_list;
    uptr allocated_user;  // Bytes allocated for user memory.
    uptr allocated_meta;  // Bytes allocated for metadata.
    uptr mapped_user;  // Bytes mapped for user memory.
    uptr mapped_meta;  // Bytes mapped for metadata.
    uptr n_allocated, n_freed;  // Just stats.
  };
  COMPILER_CHECK(sizeof(RegionInfo) >= kCacheLineSize);

  static uptr AdditionalSize() {
    return RoundUpTo(sizeof(RegionInfo) * kNumClassesRounded,
                     GetPageSizeCached());
  }

  RegionInfo *GetRegionInfo(uptr class_id) {
    CHECK_LT(class_id, kNumClasses);
    RegionInfo *regions = reinterpret_cast<RegionInfo*>(kSpaceBeg + kSpaceSize);
    return &regions[class_id];
  }

  static uptr GetChunkIdx(uptr chunk, uptr size) {
    uptr offset = chunk % kRegionSize;
    // Here we divide by a non-constant. This is costly.
    // size always fits into 32-bits. If the offset fits too, use 32-bit div.
    if (offset >> (SANITIZER_WORDSIZE / 2))
      return offset / size;
    return (u32)offset / (u32)size;
  }

  NOINLINE Batch* PopulateFreeList(AllocatorStats *stat, AllocatorCache *c,
                                   uptr class_id, RegionInfo *region) {
    BlockingMutexLock l(&region->mutex);
    Batch *b = region->free_list.Pop();
    if (b)
      return b;
    uptr size = SizeClassMap::Size(class_id);
    uptr count = size < kPopulateSize ? SizeClassMap::MaxCached(class_id) : 1;
    uptr beg_idx = region->allocated_user;
    uptr end_idx = beg_idx + count * size;
    uptr region_beg = kSpaceBeg + kRegionSize * class_id;
    if (end_idx + size > region->mapped_user) {
      // Do the mmap for the user memory.
      uptr map_size = kUserMapSize;
      while (end_idx + size > region->mapped_user + map_size)
        map_size += kUserMapSize;
      CHECK_GE(region->mapped_user + map_size, end_idx);
      MapWithCallback(region_beg + region->mapped_user, map_size);
      stat->Add(AllocatorStatMmapped, map_size);
      region->mapped_user += map_size;
    }
    uptr total_count = (region->mapped_user - beg_idx - size)
        / size / count * count;
    region->allocated_meta += total_count * kMetadataSize;
    if (region->allocated_meta > region->mapped_meta) {
      uptr map_size = kMetaMapSize;
      while (region->allocated_meta > region->mapped_meta + map_size)
        map_size += kMetaMapSize;
      // Do the mmap for the metadata.
      CHECK_GE(region->mapped_meta + map_size, region->allocated_meta);
      MapWithCallback(region_beg + kRegionSize -
                      region->mapped_meta - map_size, map_size);
      region->mapped_meta += map_size;
    }
    CHECK_LE(region->allocated_meta, region->mapped_meta);
    if (region->mapped_user + region->mapped_meta > kRegionSize) {
      Printf("%s: Out of memory. Dying. ", SanitizerToolName);
      Printf("The process has exhausted %zuMB for size class %zu.\n",
          kRegionSize / 1024 / 1024, size);
      Die();
    }
    for (;;) {
      if (SizeClassMap::SizeClassRequiresSeparateTransferBatch(class_id))
        b = (Batch*)c->Allocate(this, SizeClassMap::ClassID(sizeof(Batch)));
      else
        b = (Batch*)(region_beg + beg_idx);
      b->count = count;
      for (uptr i = 0; i < count; i++)
        b->batch[i] = (void*)(region_beg + beg_idx + i * size);
      region->allocated_user += count * size;
      CHECK_LE(region->allocated_user, region->mapped_user);
      beg_idx += count * size;
      if (beg_idx + count * size + size > region->mapped_user)
        break;
      CHECK_GT(b->count, 0);
      region->free_list.Push(b);
    }
    return b;
  }
};

// Maps integers in rage [0, kSize) to u8 values.
template<u64 kSize>
class FlatByteMap {
 public:
  void TestOnlyInit() {
    internal_memset(map_, 0, sizeof(map_));
  }

  void set(uptr idx, u8 val) {
    CHECK_LT(idx, kSize);
    CHECK_EQ(0U, map_[idx]);
    map_[idx] = val;
  }
  u8 operator[] (uptr idx) {
    CHECK_LT(idx, kSize);
    // FIXME: CHECK may be too expensive here.
    return map_[idx];
  }
 private:
  u8 map_[kSize];
};

// FIXME: Also implement TwoLevelByteMap.

// SizeClassAllocator32 -- allocator for 32-bit address space.
// This allocator can theoretically be used on 64-bit arch, but there it is less
// efficient than SizeClassAllocator64.
//
// [kSpaceBeg, kSpaceBeg + kSpaceSize) is the range of addresses which can
// be returned by MmapOrDie().
//
// Region:
//   a result of a single call to MmapAlignedOrDie(kRegionSize, kRegionSize).
// Since the regions are aligned by kRegionSize, there are exactly
// kNumPossibleRegions possible regions in the address space and so we keep
// a ByteMap possible_regions to store the size classes of each Region.
// 0 size class means the region is not used by the allocator.
//
// One Region is used to allocate chunks of a single size class.
// A Region looks like this:
// UserChunk1 .. UserChunkN <gap> MetaChunkN .. MetaChunk1
//
// In order to avoid false sharing the objects of this class should be
// chache-line aligned.
template <const uptr kSpaceBeg, const u64 kSpaceSize,
          const uptr kMetadataSize, class SizeClassMap,
          const uptr kRegionSizeLog,
          class ByteMap,
          class MapUnmapCallback = NoOpMapUnmapCallback>
class SizeClassAllocator32 {
 public:
  typedef typename SizeClassMap::TransferBatch Batch;
  typedef SizeClassAllocator32<kSpaceBeg, kSpaceSize, kMetadataSize,
      SizeClassMap, kRegionSizeLog, ByteMap, MapUnmapCallback> ThisT;
  typedef SizeClassAllocatorLocalCache<ThisT> AllocatorCache;

  void Init() {
    possible_regions.TestOnlyInit();
    internal_memset(size_class_info_array, 0, sizeof(size_class_info_array));
  }

  void *MapWithCallback(uptr size) {
    size = RoundUpTo(size, GetPageSizeCached());
    void *res = MmapOrDie(size, "SizeClassAllocator32");
    MapUnmapCallback().OnMap((uptr)res, size);
    return res;
  }

  void UnmapWithCallback(uptr beg, uptr size) {
    MapUnmapCallback().OnUnmap(beg, size);
    UnmapOrDie(reinterpret_cast<void *>(beg), size);
  }

  static bool CanAllocate(uptr size, uptr alignment) {
    return size <= SizeClassMap::kMaxSize &&
      alignment <= SizeClassMap::kMaxSize;
  }

  void *GetMetaData(const void *p) {
    CHECK(PointerIsMine(p));
    uptr mem = reinterpret_cast<uptr>(p);
    uptr beg = ComputeRegionBeg(mem);
    uptr size = SizeClassMap::Size(GetSizeClass(p));
    u32 offset = mem - beg;
    uptr n = offset / (u32)size;  // 32-bit division
    uptr meta = (beg + kRegionSize) - (n + 1) * kMetadataSize;
    return reinterpret_cast<void*>(meta);
  }

  NOINLINE Batch* AllocateBatch(AllocatorStats *stat, AllocatorCache *c,
                                uptr class_id) {
    CHECK_LT(class_id, kNumClasses);
    SizeClassInfo *sci = GetSizeClassInfo(class_id);
    SpinMutexLock l(&sci->mutex);
    if (sci->free_list.empty())
      PopulateFreeList(stat, c, sci, class_id);
    CHECK(!sci->free_list.empty());
    Batch *b = sci->free_list.front();
    sci->free_list.pop_front();
    return b;
  }

  NOINLINE void DeallocateBatch(AllocatorStats *stat, uptr class_id, Batch *b) {
    CHECK_LT(class_id, kNumClasses);
    SizeClassInfo *sci = GetSizeClassInfo(class_id);
    SpinMutexLock l(&sci->mutex);
    CHECK_GT(b->count, 0);
    sci->free_list.push_front(b);
  }

  bool PointerIsMine(const void *p) {
    return GetSizeClass(p) != 0;
  }

  uptr GetSizeClass(const void *p) {
    return possible_regions[ComputeRegionId(reinterpret_cast<uptr>(p))];
  }

  void *GetBlockBegin(const void *p) {
    CHECK(PointerIsMine(p));
    uptr mem = reinterpret_cast<uptr>(p);
    uptr beg = ComputeRegionBeg(mem);
    uptr size = SizeClassMap::Size(GetSizeClass(p));
    u32 offset = mem - beg;
    u32 n = offset / (u32)size;  // 32-bit division
    uptr res = beg + (n * (u32)size);
    return reinterpret_cast<void*>(res);
  }

  uptr GetActuallyAllocatedSize(void *p) {
    CHECK(PointerIsMine(p));
    return SizeClassMap::Size(GetSizeClass(p));
  }

  uptr ClassID(uptr size) { return SizeClassMap::ClassID(size); }

  uptr TotalMemoryUsed() {
    // No need to lock here.
    uptr res = 0;
    for (uptr i = 0; i < kNumPossibleRegions; i++)
      if (possible_regions[i])
        res += kRegionSize;
    return res;
  }

  void TestOnlyUnmap() {
    for (uptr i = 0; i < kNumPossibleRegions; i++)
      if (possible_regions[i])
        UnmapWithCallback((i * kRegionSize), kRegionSize);
  }

  // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
  // introspection API.
  void ForceLock() {
    for (uptr i = 0; i < kNumClasses; i++) {
      GetSizeClassInfo(i)->mutex.Lock();
    }
  }

  void ForceUnlock() {
    for (int i = kNumClasses - 1; i >= 0; i--) {
      GetSizeClassInfo(i)->mutex.Unlock();
    }
  }

  // Iterate over all existing chunks.
  // The allocator must be locked when calling this function.
  void ForEachChunk(ForEachChunkCallback callback, void *arg) {
    for (uptr region = 0; region < kNumPossibleRegions; region++)
      if (possible_regions[region]) {
        uptr chunk_size = SizeClassMap::Size(possible_regions[region]);
        uptr max_chunks_in_region = kRegionSize / (chunk_size + kMetadataSize);
        uptr region_beg = region * kRegionSize;
        for (uptr chunk = region_beg;
             chunk < region_beg + max_chunks_in_region * chunk_size;
             chunk += chunk_size) {
          // Too slow: CHECK_EQ((void *)chunk, GetBlockBegin((void *)chunk));
          callback(chunk, arg);
        }
      }
  }

  void PrintStats() {
  }

  typedef SizeClassMap SizeClassMapT;
  static const uptr kNumClasses = SizeClassMap::kNumClasses;

 private:
  static const uptr kRegionSize = 1 << kRegionSizeLog;
  static const uptr kNumPossibleRegions = kSpaceSize / kRegionSize;

  struct SizeClassInfo {
    SpinMutex mutex;
    IntrusiveList<Batch> free_list;
    char padding[kCacheLineSize - sizeof(uptr) - sizeof(IntrusiveList<Batch>)];
  };
  COMPILER_CHECK(sizeof(SizeClassInfo) == kCacheLineSize);

  uptr ComputeRegionId(uptr mem) {
    uptr res = mem >> kRegionSizeLog;
    CHECK_LT(res, kNumPossibleRegions);
    return res;
  }

  uptr ComputeRegionBeg(uptr mem) {
    return mem & ~(kRegionSize - 1);
  }

  uptr AllocateRegion(AllocatorStats *stat, uptr class_id) {
    CHECK_LT(class_id, kNumClasses);
    uptr res = reinterpret_cast<uptr>(MmapAlignedOrDie(kRegionSize, kRegionSize,
                                      "SizeClassAllocator32"));
    MapUnmapCallback().OnMap(res, kRegionSize);
    stat->Add(AllocatorStatMmapped, kRegionSize);
    CHECK_EQ(0U, (res & (kRegionSize - 1)));
    possible_regions.set(ComputeRegionId(res), static_cast<u8>(class_id));
    return res;
  }

  SizeClassInfo *GetSizeClassInfo(uptr class_id) {
    CHECK_LT(class_id, kNumClasses);
    return &size_class_info_array[class_id];
  }

  void PopulateFreeList(AllocatorStats *stat, AllocatorCache *c,
                        SizeClassInfo *sci, uptr class_id) {
    uptr size = SizeClassMap::Size(class_id);
    uptr reg = AllocateRegion(stat, class_id);
    uptr n_chunks = kRegionSize / (size + kMetadataSize);
    uptr max_count = SizeClassMap::MaxCached(class_id);
    Batch *b = 0;
    for (uptr i = reg; i < reg + n_chunks * size; i += size) {
      if (b == 0) {
        if (SizeClassMap::SizeClassRequiresSeparateTransferBatch(class_id))
          b = (Batch*)c->Allocate(this, SizeClassMap::ClassID(sizeof(Batch)));
        else
          b = (Batch*)i;
        b->count = 0;
      }
      b->batch[b->count++] = (void*)i;
      if (b->count == max_count) {
        CHECK_GT(b->count, 0);
        sci->free_list.push_back(b);
        b = 0;
      }
    }
    if (b) {
      CHECK_GT(b->count, 0);
      sci->free_list.push_back(b);
    }
  }

  ByteMap possible_regions;
  SizeClassInfo size_class_info_array[kNumClasses];
};

// Objects of this type should be used as local caches for SizeClassAllocator64
// or SizeClassAllocator32. Since the typical use of this class is to have one
// object per thread in TLS, is has to be POD.
template<class SizeClassAllocator>
struct SizeClassAllocatorLocalCache {
  typedef SizeClassAllocator Allocator;
  static const uptr kNumClasses = SizeClassAllocator::kNumClasses;

  void Init(AllocatorGlobalStats *s) {
    stats_.Init();
    if (s)
      s->Register(&stats_);
  }

  void Destroy(SizeClassAllocator *allocator, AllocatorGlobalStats *s) {
    Drain(allocator);
    if (s)
      s->Unregister(&stats_);
  }

  void *Allocate(SizeClassAllocator *allocator, uptr class_id) {
    CHECK_NE(class_id, 0UL);
    CHECK_LT(class_id, kNumClasses);
    stats_.Add(AllocatorStatMalloced, SizeClassMap::Size(class_id));
    PerClass *c = &per_class_[class_id];
    if (UNLIKELY(c->count == 0))
      Refill(allocator, class_id);
    void *res = c->batch[--c->count];
    PREFETCH(c->batch[c->count - 1]);
    return res;
  }

  void Deallocate(SizeClassAllocator *allocator, uptr class_id, void *p) {
    CHECK_NE(class_id, 0UL);
    CHECK_LT(class_id, kNumClasses);
    // If the first allocator call on a new thread is a deallocation, then
    // max_count will be zero, leading to check failure.
    InitCache();
    stats_.Add(AllocatorStatFreed, SizeClassMap::Size(class_id));
    PerClass *c = &per_class_[class_id];
    CHECK_NE(c->max_count, 0UL);
    if (UNLIKELY(c->count == c->max_count))
      Drain(allocator, class_id);
    c->batch[c->count++] = p;
  }

  void Drain(SizeClassAllocator *allocator) {
    for (uptr class_id = 0; class_id < kNumClasses; class_id++) {
      PerClass *c = &per_class_[class_id];
      while (c->count > 0)
        Drain(allocator, class_id);
    }
  }

  // private:
  typedef typename SizeClassAllocator::SizeClassMapT SizeClassMap;
  typedef typename SizeClassMap::TransferBatch Batch;
  struct PerClass {
    uptr count;
    uptr max_count;
    void *batch[2 * SizeClassMap::kMaxNumCached];
  };
  PerClass per_class_[kNumClasses];
  AllocatorStats stats_;

  void InitCache() {
    if (per_class_[1].max_count)
      return;
    for (uptr i = 0; i < kNumClasses; i++) {
      PerClass *c = &per_class_[i];
      c->max_count = 2 * SizeClassMap::MaxCached(i);
    }
  }

  NOINLINE void Refill(SizeClassAllocator *allocator, uptr class_id) {
    InitCache();
    PerClass *c = &per_class_[class_id];
    Batch *b = allocator->AllocateBatch(&stats_, this, class_id);
    CHECK_GT(b->count, 0);
    for (uptr i = 0; i < b->count; i++)
      c->batch[i] = b->batch[i];
    c->count = b->count;
    if (SizeClassMap::SizeClassRequiresSeparateTransferBatch(class_id))
      Deallocate(allocator, SizeClassMap::ClassID(sizeof(Batch)), b);
  }

  NOINLINE void Drain(SizeClassAllocator *allocator, uptr class_id) {
    InitCache();
    PerClass *c = &per_class_[class_id];
    Batch *b;
    if (SizeClassMap::SizeClassRequiresSeparateTransferBatch(class_id))
      b = (Batch*)Allocate(allocator, SizeClassMap::ClassID(sizeof(Batch)));
    else
      b = (Batch*)c->batch[0];
    uptr cnt = Min(c->max_count / 2, c->count);
    for (uptr i = 0; i < cnt; i++) {
      b->batch[i] = c->batch[i];
      c->batch[i] = c->batch[i + c->max_count / 2];
    }
    b->count = cnt;
    c->count -= cnt;
    CHECK_GT(b->count, 0);
    allocator->DeallocateBatch(&stats_, class_id, b);
  }
};

// This class can (de)allocate only large chunks of memory using mmap/unmap.
// The main purpose of this allocator is to cover large and rare allocation
// sizes not covered by more efficient allocators (e.g. SizeClassAllocator64).
template <class MapUnmapCallback = NoOpMapUnmapCallback>
class LargeMmapAllocator {
 public:
  void Init() {
    internal_memset(this, 0, sizeof(*this));
    page_size_ = GetPageSizeCached();
  }

  void *Allocate(AllocatorStats *stat, uptr size, uptr alignment) {
    CHECK(IsPowerOfTwo(alignment));
    uptr map_size = RoundUpMapSize(size);
    if (alignment > page_size_)
      map_size += alignment;
    if (map_size < size) return 0;  // Overflow.
    uptr map_beg = reinterpret_cast<uptr>(
        MmapOrDie(map_size, "LargeMmapAllocator"));
    MapUnmapCallback().OnMap(map_beg, map_size);
    uptr map_end = map_beg + map_size;
    uptr res = map_beg + page_size_;
    if (res & (alignment - 1))  // Align.
      res += alignment - (res & (alignment - 1));
    CHECK_EQ(0, res & (alignment - 1));
    CHECK_LE(res + size, map_end);
    Header *h = GetHeader(res);
    h->size = size;
    h->map_beg = map_beg;
    h->map_size = map_size;
    uptr size_log = MostSignificantSetBitIndex(map_size);
    CHECK_LT(size_log, ARRAY_SIZE(stats.by_size_log));
    {
      SpinMutexLock l(&mutex_);
      uptr idx = n_chunks_++;
      chunks_sorted_ = false;
      CHECK_LT(idx, kMaxNumChunks);
      h->chunk_idx = idx;
      chunks_[idx] = h;
      stats.n_allocs++;
      stats.currently_allocated += map_size;
      stats.max_allocated = Max(stats.max_allocated, stats.currently_allocated);
      stats.by_size_log[size_log]++;
      stat->Add(AllocatorStatMalloced, map_size);
      stat->Add(AllocatorStatMmapped, map_size);
    }
    return reinterpret_cast<void*>(res);
  }

  void Deallocate(AllocatorStats *stat, void *p) {
    Header *h = GetHeader(p);
    {
      SpinMutexLock l(&mutex_);
      uptr idx = h->chunk_idx;
      CHECK_EQ(chunks_[idx], h);
      CHECK_LT(idx, n_chunks_);
      chunks_[idx] = chunks_[n_chunks_ - 1];
      chunks_[idx]->chunk_idx = idx;
      n_chunks_--;
      chunks_sorted_ = false;
      stats.n_frees++;
      stats.currently_allocated -= h->map_size;
      stat->Add(AllocatorStatFreed, h->map_size);
      stat->Add(AllocatorStatUnmapped, h->map_size);
    }
    MapUnmapCallback().OnUnmap(h->map_beg, h->map_size);
    UnmapOrDie(reinterpret_cast<void*>(h->map_beg), h->map_size);
  }

  uptr TotalMemoryUsed() {
    SpinMutexLock l(&mutex_);
    uptr res = 0;
    for (uptr i = 0; i < n_chunks_; i++) {
      Header *h = chunks_[i];
      CHECK_EQ(h->chunk_idx, i);
      res += RoundUpMapSize(h->size);
    }
    return res;
  }

  bool PointerIsMine(const void *p) {
    return GetBlockBegin(p) != 0;
  }

  uptr GetActuallyAllocatedSize(void *p) {
    return RoundUpTo(GetHeader(p)->size, page_size_);
  }

  // At least page_size_/2 metadata bytes is available.
  void *GetMetaData(const void *p) {
    // Too slow: CHECK_EQ(p, GetBlockBegin(p));
    CHECK(IsAligned(reinterpret_cast<uptr>(p), page_size_));
    return GetHeader(p) + 1;
  }

  void *GetBlockBegin(const void *ptr) {
    uptr p = reinterpret_cast<uptr>(ptr);
    SpinMutexLock l(&mutex_);
    uptr nearest_chunk = 0;
    // Cache-friendly linear search.
    for (uptr i = 0; i < n_chunks_; i++) {
      uptr ch = reinterpret_cast<uptr>(chunks_[i]);
      if (p < ch) continue;  // p is at left to this chunk, skip it.
      if (p - ch < p - nearest_chunk)
        nearest_chunk = ch;
    }
    if (!nearest_chunk)
      return 0;
    Header *h = reinterpret_cast<Header *>(nearest_chunk);
    CHECK_GE(nearest_chunk, h->map_beg);
    CHECK_LT(nearest_chunk, h->map_beg + h->map_size);
    CHECK_LE(nearest_chunk, p);
    if (h->map_beg + h->map_size <= p)
      return 0;
    return GetUser(h);
  }

  // This function does the same as GetBlockBegin, but is much faster.
  // Must be called with the allocator locked.
  void *GetBlockBeginFastLocked(void *ptr) {
    uptr p = reinterpret_cast<uptr>(ptr);
    uptr n = n_chunks_;
    if (!n) return 0;
    if (!chunks_sorted_) {
      // Do one-time sort. chunks_sorted_ is reset in Allocate/Deallocate.
      SortArray(reinterpret_cast<uptr*>(chunks_), n);
      for (uptr i = 0; i < n; i++)
        chunks_[i]->chunk_idx = i;
      chunks_sorted_ = true;
      min_mmap_ = reinterpret_cast<uptr>(chunks_[0]);
      max_mmap_ = reinterpret_cast<uptr>(chunks_[n - 1]) +
          chunks_[n - 1]->map_size;
    }
    if (p < min_mmap_ || p >= max_mmap_)
      return 0;
    uptr beg = 0, end = n - 1;
    // This loop is a log(n) lower_bound. It does not check for the exact match
    // to avoid expensive cache-thrashing loads.
    while (end - beg >= 2) {
      uptr mid = (beg + end) / 2;  // Invariant: mid >= beg + 1
      if (p < reinterpret_cast<uptr>(chunks_[mid]))
        end = mid - 1;  // We are not interested in chunks_[mid].
      else
        beg = mid;  // chunks_[mid] may still be what we want.
    }

    if (beg < end) {
      CHECK_EQ(beg + 1, end);
      // There are 2 chunks left, choose one.
      if (p >= reinterpret_cast<uptr>(chunks_[end]))
        beg = end;
    }

    Header *h = chunks_[beg];
    if (h->map_beg + h->map_size <= p || p < h->map_beg)
      return 0;
    return GetUser(h);
  }

  void PrintStats() {
    Printf("Stats: LargeMmapAllocator: allocated %zd times, "
           "remains %zd (%zd K) max %zd M; by size logs: ",
           stats.n_allocs, stats.n_allocs - stats.n_frees,
           stats.currently_allocated >> 10, stats.max_allocated >> 20);
    for (uptr i = 0; i < ARRAY_SIZE(stats.by_size_log); i++) {
      uptr c = stats.by_size_log[i];
      if (!c) continue;
      Printf("%zd:%zd; ", i, c);
    }
    Printf("\n");
  }

  // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
  // introspection API.
  void ForceLock() {
    mutex_.Lock();
  }

  void ForceUnlock() {
    mutex_.Unlock();
  }

  // Iterate over all existing chunks.
  // The allocator must be locked when calling this function.
  void ForEachChunk(ForEachChunkCallback callback, void *arg) {
    for (uptr i = 0; i < n_chunks_; i++)
      callback(reinterpret_cast<uptr>(GetUser(chunks_[i])), arg);
  }

 private:
  static const int kMaxNumChunks = 1 << FIRST_32_SECOND_64(15, 18);
  struct Header {
    uptr map_beg;
    uptr map_size;
    uptr size;
    uptr chunk_idx;
  };

  Header *GetHeader(uptr p) {
    CHECK(IsAligned(p, page_size_));
    return reinterpret_cast<Header*>(p - page_size_);
  }
  Header *GetHeader(const void *p) {
    return GetHeader(reinterpret_cast<uptr>(p));
  }

  void *GetUser(Header *h) {
    CHECK(IsAligned((uptr)h, page_size_));
    return reinterpret_cast<void*>(reinterpret_cast<uptr>(h) + page_size_);
  }

  uptr RoundUpMapSize(uptr size) {
    return RoundUpTo(size, page_size_) + page_size_;
  }

  uptr page_size_;
  Header *chunks_[kMaxNumChunks];
  uptr n_chunks_;
  uptr min_mmap_, max_mmap_;
  bool chunks_sorted_;
  struct Stats {
    uptr n_allocs, n_frees, currently_allocated, max_allocated, by_size_log[64];
  } stats;
  SpinMutex mutex_;
};

// This class implements a complete memory allocator by using two
// internal allocators:
// PrimaryAllocator is efficient, but may not allocate some sizes (alignments).
//  When allocating 2^x bytes it should return 2^x aligned chunk.
// PrimaryAllocator is used via a local AllocatorCache.
// SecondaryAllocator can allocate anything, but is not efficient.
template <class PrimaryAllocator, class AllocatorCache,
          class SecondaryAllocator>  // NOLINT
class CombinedAllocator {
 public:
  void Init() {
    primary_.Init();
    secondary_.Init();
    stats_.Init();
  }

  void *Allocate(AllocatorCache *cache, uptr size, uptr alignment,
                 bool cleared = false) {
    // Returning 0 on malloc(0) may break a lot of code.
    if (size == 0)
      size = 1;
    if (size + alignment < size)
      return 0;
    if (alignment > 8)
      size = RoundUpTo(size, alignment);
    void *res;
    if (primary_.CanAllocate(size, alignment))
      res = cache->Allocate(&primary_, primary_.ClassID(size));
    else
      res = secondary_.Allocate(&stats_, size, alignment);
    if (alignment > 8)
      CHECK_EQ(reinterpret_cast<uptr>(res) & (alignment - 1), 0);
    if (cleared && res)
      internal_memset(res, 0, size);
    return res;
  }

  void Deallocate(AllocatorCache *cache, void *p) {
    if (!p) return;
    if (primary_.PointerIsMine(p))
      cache->Deallocate(&primary_, primary_.GetSizeClass(p), p);
    else
      secondary_.Deallocate(&stats_, p);
  }

  void *Reallocate(AllocatorCache *cache, void *p, uptr new_size,
                   uptr alignment) {
    if (!p)
      return Allocate(cache, new_size, alignment);
    if (!new_size) {
      Deallocate(cache, p);
      return 0;
    }
    CHECK(PointerIsMine(p));
    uptr old_size = GetActuallyAllocatedSize(p);
    uptr memcpy_size = Min(new_size, old_size);
    void *new_p = Allocate(cache, new_size, alignment);
    if (new_p)
      internal_memcpy(new_p, p, memcpy_size);
    Deallocate(cache, p);
    return new_p;
  }

  bool PointerIsMine(void *p) {
    if (primary_.PointerIsMine(p))
      return true;
    return secondary_.PointerIsMine(p);
  }

  bool FromPrimary(void *p) {
    return primary_.PointerIsMine(p);
  }

  void *GetMetaData(const void *p) {
    if (primary_.PointerIsMine(p))
      return primary_.GetMetaData(p);
    return secondary_.GetMetaData(p);
  }

  void *GetBlockBegin(const void *p) {
    if (primary_.PointerIsMine(p))
      return primary_.GetBlockBegin(p);
    return secondary_.GetBlockBegin(p);
  }

  // This function does the same as GetBlockBegin, but is much faster.
  // Must be called with the allocator locked.
  void *GetBlockBeginFastLocked(void *p) {
    if (primary_.PointerIsMine(p))
      return primary_.GetBlockBegin(p);
    return secondary_.GetBlockBeginFastLocked(p);
  }

  uptr GetActuallyAllocatedSize(void *p) {
    if (primary_.PointerIsMine(p))
      return primary_.GetActuallyAllocatedSize(p);
    return secondary_.GetActuallyAllocatedSize(p);
  }

  uptr TotalMemoryUsed() {
    return primary_.TotalMemoryUsed() + secondary_.TotalMemoryUsed();
  }

  void TestOnlyUnmap() { primary_.TestOnlyUnmap(); }

  void InitCache(AllocatorCache *cache) {
    cache->Init(&stats_);
  }

  void DestroyCache(AllocatorCache *cache) {
    cache->Destroy(&primary_, &stats_);
  }

  void SwallowCache(AllocatorCache *cache) {
    cache->Drain(&primary_);
  }

  void GetStats(AllocatorStatCounters s) const {
    stats_.Get(s);
  }

  void PrintStats() {
    primary_.PrintStats();
    secondary_.PrintStats();
  }

  // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
  // introspection API.
  void ForceLock() {
    primary_.ForceLock();
    secondary_.ForceLock();
  }

  void ForceUnlock() {
    secondary_.ForceUnlock();
    primary_.ForceUnlock();
  }

  // Iterate over all existing chunks.
  // The allocator must be locked when calling this function.
  void ForEachChunk(ForEachChunkCallback callback, void *arg) {
    primary_.ForEachChunk(callback, arg);
    secondary_.ForEachChunk(callback, arg);
  }

 private:
  PrimaryAllocator primary_;
  SecondaryAllocator secondary_;
  AllocatorGlobalStats stats_;
};

// Returns true if calloc(size, n) should return 0 due to overflow in size*n.
bool CallocShouldReturnNullDueToOverflow(uptr size, uptr n);

}  // namespace __sanitizer

#endif  // SANITIZER_ALLOCATOR_H


It's still not clear when the highly anticipated Palm Pre smartphone will ship or how much it'll cost, but at least we know a bit more about its wireless plans. During Tuesday's promotional Webcast for the so-called iPhone killer, Sprint and Palm dribbled out a few additional Pre factoids, but they were mum on the phone's ship date. As it stands, the Pre should appear in the first half of this year.
· Individuals can choose from 450-minute ($69.99), 900-minute ($89.99) or unlimited plans ($99.99).
· Families can choose from 1500 minutes ($129.99), 3000 minutes ($169.99) or unlimited plans ($189.99).
· Business customers will be able to pool their minutes using 5 (or so) plans.
At first glance, the Pre's plans appear competitive, and the unlimited-use options should prove popular with heavy web users. Sprint has been very aggressive lately with its all-you-can-use deals; its Boost Mobile subsidiary even offers a $50 plan with unlimited voice, messaging, and text.
Unfortunately, beyond the price-plan specifics, the Sprint/Palm webcast was mostly a big tease. In addition to the murky ship date, the world wants to know what the handset will cost, and whether the Pre will live up to its pre-release hype. If Sprint and Palm stick to their original ship date, we should know soon enough.


The pedestrian bridges in McPherson Park are complete.
Please note: the site plan is not final and is subject to change.
Construction is still confirmed for March 2019 with an estimated completion date in late April 2019.


Substance use can start as a pleasurable social lubricant bringing friends together, but it can also spin out of control into terrible heartache, loneliness, loss and even death. What I hope to do is create an environment where we can explore your concerns and figure out what you can do to minimize or eliminate the risks of substance use and find the solutions that work for you. Each individual is unique; just as the substances used vary, so can the best approach to treatment.
I also work frequently with the partners of those with substance abuse issues. It seems like some people are simply destined to choose partners who have some kind of problem controlling their substance use, and these individuals end up spending their life trying to help. I work with the partners just as much as the substance abuser and, while the work is different, I know how to help.
"Brain Function Can Return After Meth Abuse"


text:
Die ehemalige Übungs- und Lehrgrenze der DDR-Grenztruppen befindet sich südöstlich von Römhild, am Fuße der Gleichberge. Sie dürfte im Zuge der Unteroffizierausbildung auf den Gleichbergen in den 1960er Jahren entstanden sein. Die Übungs- und Lehrgrenze diente der Ausbildung von DDR-Grenzsoldaten im täglichen Grenzdienst. Damit die Tätigkeiten und Ausbildungen von westlicher Seite nicht beobachtet und aufgeklärt werden konnten, waren Übungs- und Lehrgrenzen oft einige Kilometer im Landesinneren der DDR an exponierten Stellen im Gelände angelegt. Die Übungs- und Lehrgrenze bei Römhild wurde im Jahr 2009 als Bodendenkmal des Freistaates Thüringen unter staatlichen Denkmalschutz gestellt.
Die Ortschaft Römhild liegt unmittelbar am Streckenverlauf der Erlebnisstraße der deutschen Einheit.

Entstehungsgeschichte
Nach der politischen Wende in der DDR hatten die Grenzanlagen keine Bedeutung mehr. Die DDR-Grenztruppen wurden daraufhin mit Wirkung zum 30. September 1990 aufgelöst. Die Übungs- und Lehrgrenzen, die sich im Inland der DDR befanden, wurden in der Folgezeit nicht ausdrücklich geräumt und gerieten oft in Vergessenheit. Nach Hinweisen aus der Bevölkerung und im Rahmen ihrer an der innerdeutschen Grenze durchgeführten Denkmalforschung entdeckte Familie Elke, Andreas und Manuel Erhard die Übungs- und Lehrgrenze auf den Gleichbergen im Jahr 2007 wieder.

Im Einzelnen handelt es sich hierbei um eine DDR-Grenzsäule, einen Erdbunker aus Betonteilen mit weit verzweigten Laufgräben, einen Teilbereich des Kfz-Sperrgrabens (mit Betonplatten ausgelegt) sowie Sicherungs- und Verteidigungsstellungen. Im Areal befinden sich noch Reste des Grenzmeldenetzes sowie unterschiedliche Stolperfallen. Alle Grenzrelikte sind im Verlauf einer nachgebildeten Grenze (Waldrand als angenommene tatsächliche Grenzlinie) aufgebaut. Markante Grenzsteine der Waldvermessung wurden integriert.

Die Übungs- und Lehrgrenze erstreckt sich auf ca. 300 Meter angenommene Grenzlinie.
Sie dürfte sich in den 1960er und 1970er Jahren auf ein bedeutend längeres Geländestück erstreckt haben. Eigentümer des Waldstückes ist der Thüringer Forst. Die Betreuung der Denkmalanlagen liegt beim Deutschen Kuratorium zur Förderung von Wissenschaft, Bildung und Kultur e.V.

Einzelnachweise

Innerdeutsche Grenze
Deutsche Teilung
Freilichtmuseum in Thüringen
Grenztruppen der DDR
Kultur (Römhild)
Militärische Einrichtung (Thüringen)
Museum im Landkreis Hildburghausen
Bildung in Römhild

redpajama_set_name: RedPajamaWikipedia


Have you seen the video – are you ready to join in with us?
If you haven't seen the show yet, here it is!
We're so glad you're interested in the 60 Minutes Australia show about IAPF and our Akashinga all-female ranger program and the elephants they protect (and of course, our founder Damien Mander, too)!
The TV show shares some great information about our work to stop poaching in Africa. 60 Minutes highlighted the fact that IAPF protects endangered African wildlife and ecosystems through our program Akashinga ("The Brave Ones"). Our conservation efforts also include two more programs in Africa: LEADRanger in Kenya, and Special Investigations in multiple counties.
and providing critical project management and administrative support to local communities engaged in preventing poaching and parts trafficking.
Will you join us and help protect elephants, rhinos, and lions in Africa?
If you have any questions, please send us an email. We'd love to hear from you!


Homelessness in Kosciusko County is bigger than many realize. In 2016, Data USA, which collects data from all over the country, estimated that 11% of Kosciusko County lives below the poverty line. One of the biggest responses to of homelessness in our area is Fellowship Missions, a faith-based nonprofit organization that provides residents a place to stay, as well as consistent meals and Christian mentoring programs designed to transform lives.
Executive director Eric Lane and his wife formed Fellowship Missions in 2010 due to the major need that they saw in the community. The organization has grown from providing emergency services to providing temporary housing, consistent meals, and programs that teach basic life skills and promote the overall well-being of the residents. The shelter has 46 beds total but, using cots as well, is able to hold around 70 people during freezing weather conditions.
There are many causes to homelessness; however, Lane considers mental illness to be the leading cause of homelessness because of its impact in every area of individual's lives. Melissa Demopoulos, the community relations director for Fellowship Missions says "the most vulnerable to homelessness are those struggling with a chronic physical or mental disorder." In fact, 85% of those who receive services at Fellowship Missions have a mental health condition and/or addiction. Much of this poverty is generational and the problem with the cycle of poverty stems from broken relationships and broken social structures.
"What we see is a need to develop meaningful, deep relationships with people because all of the success stories we have seen are folks who have been nurtured through living relationship where they are seen and heard and known," says Demopoulos.
Because Fellowship Missions is a faith-based organization, it does not qualify for state or federal funding, which makes Fellowship Missions entirely reliant on donations from the community. With only four full time staff and one part time staff, Lane says that aside from monetary donations, one of their biggest needs is volunteers. Lane and Demopoulos say that the shelter always needs volunteers to help serve meals in the kitchen, as well as volunteers to come and spend time with the residents, especially the children.
Starting in 2019, Fellowship Missions will be opening up their own crowdfunding platform, so individuals can help raise funds for the shelter. They also will be beginning quarterly tours of their facility that is open to the public. The first quarterly tour of 2019 will be on January 8 with three 30 minute tour times throughout the day, one at 8 a.m., one at 12 p.m., and one at 6 p.m. However, the organization is always open to scheduling tours to those who are interested.
For more information about Fellowship Missions, visit fellowshipmissions.net.
Image above: Fellowship Missions provides hope for the homeless of the Warsaw/Winona Lake area. It is located at 1520 Winona Ave., Warsaw.


Over time, or after an injury, you might notice that your pet isn't as frisky as they used to be. Chances are this isn't just them "getting old," most likely your pet is suffering from arthritis – a disease that can be managed. Dr. Kremer teaches you all about this condition and how it can be managed in your pet.


Blink is a full-scale, mobile intranet software and app, with Hub as its central feature. Now, employees can quickly access policies, procedures, and guides in one convenience place—resulting in a more engaged, more productive workforce.
No app switching necessary! Use Hub to share the documents and other content that empower your workforce.
Hub makes your files easily available to the teams that need them, on the mobile devices they always have with them.
Our native mobile apps support built-in document previews to reduce fatigue, frustration, and burnout caused by app-switching. Intranet software has never been this useful.
Store policies, procedures, rotas, pitch decks, manuals, health and safety information, and more in Hub.
Make them all available to your frontline workforce via our award-winning mobile intranet software.
Hub gives everyone what they need, right on their device. No more paper copies. Centralized file management = less time wasted hunting down resources = more productivity.
Garage mechanics can access engineering manuals without workflow disruptions, whether they're working on fleets of buses or individual cars.
Everyone on the job site is on the same page when project updates, timeline changes, and emergency notifications are shared on Hub with your construction crew and foremen.
With Blink's intranet software, retail workers can see new additions to inventory, evolving sales goals, and scheduling updates in real time.
It's not just about access. Files in Hub can be shared with specific audiences using Blink Teams.
You're in control of who sees which documents, so you know they're secure and your employees only see things that are relevant to them.
Blink's simple and unique sharing model means that Hub will scale well over time. Growth will never derail your internal communications.
Your employee intranet stays organized because documents on Hub are managed by Blink administrators through our simple file manager.
It's easy to upload and share resources, making them instantly available to your workforce, but you control who has access and when.
Our straightforward sharing model means you'll never share files to the wrong audience. It's an extra layer of security and privacy built right into our mobile intranet software.
Blink integrates with hundreds of other software platforms and applications, by itself and with Zapier.
Create and share shortcuts with your Teams so that resources (files, forms, documents, videos, and more) stored elsewhere can still be found and accessed through Hub.
You can also publish Micro-Apps in Hub to empower the right teams with the right workflow processes.
Hub's familiar folder structure makes it easy for employees to find what they're looking for. Even if they're not technically savvy.
Messaging features to form the backbone of our modern mobile intranet software.
Blink is the only app your employees need to stay engaged and get the job done. More than just a document storage solution, Blink is a collaborative digital workspace.


Home Video Studio: Audio and Video Tape Repair! Video Transfers to DVD, Film Transfers to DVD, We Do It All!
Audio and Video Tape Repair! Video Transfers to DVD, Film Transfers to DVD, We Do It All!
We do Audio and Video Tape Repair!
Do you have Round Reels of Film?


text:
Stage 12: Tour de France
By Cycling News June 18, 2019 10:18am
Updated: June 18, 2019 10:18am Race: Tour de Suisse
Degenkolb: Peter Sagan went 'over the limit' in Tour de Suisse run-in
'I had to fight for my teammate's wheel and it was super crazy against him' says German
John Degenkolb during stage 2 at Tour de Suisse
Peter Sagan (Bora-Hansgrohe) wins stage 3 at the Tour de Suisse
Peter Sagan (Bora-Hansgrohe) wins stage 3 at the Tour de Suisse, takes overall lead
John Degenkolb (Trek-Segafredo) shows the effort during stage 7 of the 2019 Tour of California
Jasper Stuyven climbs the Taaienberg during Tour of Flanders
John Degenkolb (Trek-Segafredo) criticised Peter Sagan for aggression that he perceived as "a little bit over the limit" as the two jostled for position in the run-in on stage 3 of the Tour de Suisse on Monday.
Degenkolb: There's one rule in Paris-Roubaix: never give up
No Tour de France for Degenkolb as Trek-Segafredo focus on Richie Porte
Tour de Suisse: Peter Sagan wins stage 3
Peter Sagan: Today was the last Tour de Suisse stage for the sprinters
Being towards the very front of the peloton was crucial, with a left-hand corner with 200 metres to go leading into the cobbled incline to the finish line.
Degenkolb's teammate Jasper Stuyven hit the front with 600 metres to go, but what seemed like a perfect manoeuvre was disrupted when Sagan muscled his way in. He and Degenkolb both barged shoulders and leaned in as they fought for the wheel but in the end it was Sagan who claimed the prime position, going on to take more speed through the corner and sprint to a comfortable victory.
Degenkolb finished third after being overtaken by Elia Viviani (Deceuninck-QuickStep), and clearly felt Sagan had overstepped the mark.
"It was looking really, really good until just before the last corner. I had to fight with Sagan for my own teammate's wheel and it was super crazy against him. I think it was a little bit over the limit," he said.
"We had the team to make a better finish than this. Yes, it's not finished, but it was a big chance today, and it probably could have ended a little bit better, so it's a little disappointing."
Nevertheless, Degenkolb, who is set to miss out on selection for the Tour de France this year, took positives from the performance of his teammates.
"It was a good day in general, the team worked really well together. Not only the guys for the leadout but also the climbers helped for the preparation," he said.
"I am happy to still come home in third place and super, super happy that we worked so well together."
Degenkolb has more opportunities to take a victory at the Tour de Suisse, with stages 4 and 5 both suited to sprinters who can climb.
Cobbles of northern France hold special memories for German
April 12, 2019 8:32am
German sprinter could to be heading to Lotto Soudal in 2020
Bora-Hansgrohe rider leads general classification heading into the mountains


Brand Intelligence™ firm marks its move from Sandton to the inner city by championing Johannesburg artists and raising funds for Malvern Primary School.
Thursday, 09 February 2017 – Johannesburg, South Africa: To celebrate its move from Sandton into Johannesburg's heartland, marketing research firm Ornico will be cutting the ribbon on its new inner city premises on Thursday 23 February 2017 at 18h00 for 18h30. As part of the celebrations, Ornico will host an auction of art to raise funds for Malvern Primary School which is situated on the corner of Jules and Frere Streets in Malvern, Johannesburg.
Ornico acquired the old Natal Bank Building situated at 90 Albertina Sisulu Road, in Johannesburg in January 2016. The building was provisionally declared a national heritage site in 1990, and is the oldest standing bank building in Johannesburg. Built immediately following the Anglo Boer War and occupied in 1903, the original construction cost of the building was £29,847. Just one block from the Johannesburg Stock Exchange and the National Bank of the South African Republic, the Natal Bank overlooked the old market square, on what was then Market Street.
The building was empty, beginning to fall into a state of disrepair, and desperately needed refurbishment. Ornico has spent the last six months working with Sakhive Construction, a Jozi based construction and restoration company, to repair and renovate the site.
To commemorate the research firm's move to this heritage site, Ornico will be holding an art auction and exhibition, called 'Bridges That Connect Us', featuring some of the city's top artists.
"Ornico's clients include some of South Africa's top brands, and we invite these brand leaders to meet some of Jozi's most valuable and emerging artists. Join us at a unique inner city event, at this historic heritage venue," says Patricios. "By supporting local, Jozi-based art and artists, we believe we celebrate Jozi's unique culture and history. Art is a language that helps us understand each other, both in pain and in joy. It also creates opportunities for related endeavours, like design and innovation, and definitely contributes to economic growth through attracting cultural tourism and even encouraging investment," the Ornico CEO adds.
While the auction takes place on Thursday 23 February at 18h00 with almost all of the artists present, the public will also be able to see the work. People who live, work and play in Johannesburg are also invited to view this art exhibition on Saturday 25 and Sunday 26 February 2017 from 09H00 to 15h00.
Mbongeni Buthelezi: An internationally acclaimed artist, Buthelezi gained renown for brightly-coloured collages made from waste plastic. However, now he manufactures his own plastic in the specific colors and density he requires. Buthelezi studied as artist-in-residence in Germany and the USA, and has exhibited at the Melrose Gallery. His work is part of official collections, including the Museum for African Art in New York, Johannesburg Art Gallery and the Spier Collection.
Tshidzo Mangena: Working mainly in charcoal, acrylic and oil, Mangena's vibrant and unexpected colour combinations create works that are rich and emotive. Mangena is inspired by human emotion, and the beauty and the mystery of the African woman. Often his work reflects his love for jazz music and the grace and elegance of jazz instruments.
Solomon Omolayo Omogboye: Working mainly with charcoal, pastel, acrylic and oil on canvas, this Nigerian expat uses colours that explode with movement and emotion. His subject matter is as varied as life itself, ranging from pastel-illumined cityscapes to energy-infused portraits. He works from his own studio space in August House, JHB, which is one of the top artist colonies in SA.
Azael Langa: Benoni-born Langa won his first art competition in Grade 6, and discovered his calling studying art in high school. His works range from whimsical and surrealistic to moody impressionist pieces. Langa says that for him, art is a lifestyle. In his own words: "My art is about socio-political activism and going about the subject I show the exploitation of the Average Joe; the corruption of the elite and bringing to the surface that which is 'out of sight, out of mind' It is also about taking the intangible events, circumstances and becoming a mediator to the public." In some of Langa's more controversial work he targets western icons and South African political figures.
Ndabuko Julukani Ntuli: Inspired by his grandfather, a painter and sculptor, Ntuli learned to paint at school and practiced while tending the family cattle in KwaZulu-Natal. His talent was recognised by the Johannesburg Art Foundation, where he was encouraged to hone his skills, especially in the art of oil painting using a palette-knife. He draws inspiration from rural and township life, drawing in traditional iconography and combining modern materials.
Johnnyguava: Born John de Gouveia, Johnny deals with self-discovery through his work. His creations use found objects, sometimes adding a comical twist to this serious conceptual base. Also trained as a professional photographer, the objects are removed from the environment they were found in and then transformed into pop-art images or collage, with themes that include decay and transformation.
Michael Tshepo Selekane: Born in the politically-charged 1980s in Uitvlag, rural Mpumalanga, Selekane was only encouraged to develop his latent talent in high school, when he moved to Mabopane to be with his mother. Later he was introduced to the Tshwaraganang Arts School in Mabopane, where he was exposed to various media, and developed oil paint techniques. A programme run by the Ifa Lethu Foundation, funded by Ausaid, was held at the centre, where Selekane was selected for further assistance and development. In a competition run by Ifa Lethu, Selekane won first prize for painting, and he gained the support of BHP Billiton. Further education at Tshwane University of Technology's Faculty of Arts was funded by the Ifa Lethu Foundation, and he has gone on to exhibit at the National Arts Festival in Grahamstown, the World Summit on Arts and Culture in Johannesburg and at various galleries across SA.
Dario Manjate Art: A graduate of one of the biggest and most vibrant community and professional printmaking facilities in Johannesburg — Artist Proof Studio — Manjate's artistic skill includes oils, watercolour, acrylics, printmaking as well as the medium he is best known for — collage. Manjate's love of art started in Alex, but was honed at Artist Proof Studio, and through various community projects such as "Work To Win," an environmental awareness project which included several murals created to uplift his surrounding township community. The winner of the Freedom of Expression Art Competition (Gaulloises Blondes) in 1996, in Johannesburg, Manjate's Curriculum Vitae includes many commissioned pieces by a variety of organizations and corporate companies. He continues to bring his unique approach to the formation of his collages and thus his work is sought after for its extraordinary qualities.
Nkhensani Rihlampfu: A painter, print maker and sculptor, Rihlampfu studied Fine and Applied Arts at the Tshwane University of Technology. He realised his B-Tech degree in 2011. Rihlampfu's uncompromising work speaks to his experience of life in Johannesburg, as well as his understanding of power, spirituality and humanity. This has seen the artist win commissions for Constitutional Hill in Johannesburg and exhibit at Absa's L'Atelier, the Grahamstown Arts Festival, the Pretoria Art Museum, the Turbine Art Fair, as well as at Arts Alive and the Jo'burg-Jo'burg show. Rihlampfu now works from his own studio space in Johannesburg.
Cebo Simphiwe Xulu, aka @Mr_MediaX, is an emerging new-media artist who is attracting attention and interest following his residency at the Fakugesi African Innovation Festival, where he exhibited a set of playing cards called Mambokadzi — based upon African symbols and African queens — in collaboration with Vuyi Chaza and Regina Kgatle. Graduating from the University of Kwa-Zulu Natal in 2011 with a BA Media and Visual arts degree, Xulu — who now calls himself Papichulo — is notable because of his use of technology in art. Xulu graduated in fine arts and media from the University of KwaZulu-Natal, but spent most of his varsity time learning how to live life as the (now deceased) popular underground comic, Mr Njejust. "Since late 2013, I decided to bring all my mother's worst nightmares to life by trying to live life as an artist and entrepreneur in the creative industry. The nightmare continues to evolve into a beautiful dream," he says.
The auction and exhibition will be curated by Dawn Sarah McGee from MB Studio Community in collaboration with Nantu Palesa Phalatsi from Tshidzo Art.
The artists have agreed to donate a percentage of the auction sales to a fund for the Malvern Primary School. "This is just a small start to what will be active, ongoing participation in the city's life, by Ornico," says Patricios. "We will continue to support education and the arts, and look forward to meeting our neighbours, working with inner city partners and suppliers, and being part of Joburg's revitalisation going forward. We sincerely hope our associates, clients and business friends can join us as we mark this milestone of our journey," he adds.